package com.xbongbong.saas.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.lfasr.concurrent.ConcurrentLockAspect;
import com.xbongbong.paas.business.rule.RuleBusinessLogger;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.constant.TimeConstant;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.PaasProcessRelatedDataEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.elasticsearch.model.PaasEsModel;
import com.xbongbong.paas.elasticsearch.pojo.XbbAggregatedPage;
import com.xbongbong.paas.elasticsearch.util.EsHelper;
import com.xbongbong.paas.elasticsearch.util.EsUtil;
import com.xbongbong.paas.elasticsearch.util.XbbElasticsearchRestTemplate;
import com.xbongbong.paas.enums.DefaultTypeEnum;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.enums.TaskTypeEnum;
import com.xbongbong.paas.field.DefaultAttrPoJo;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.ItemPoJo;
import com.xbongbong.paas.field.MultiUnitItemPoJo;
import com.xbongbong.paas.field.SubFormPoJo;
import com.xbongbong.paas.field.UnitItemPoJo;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.paas.help.FormDataValidateProductHelp;
import com.xbongbong.paas.help.ProFormHelp;
import com.xbongbong.paas.help.ProSaveHelp;
import com.xbongbong.paas.help.UserHelp;
import com.xbongbong.paas.help.subform.TransferSubFormHelper;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.constant.LogMemoConstant;
import com.xbongbong.paas.log.pojo.InfoArrPojo;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasProcessRelatedDataModel;
import com.xbongbong.paas.model.PaasProcessTemplateModel;
import com.xbongbong.paas.pojo.AttrValuePojo;
import com.xbongbong.paas.pojo.FieldAttrEntityForImport;
import com.xbongbong.paas.pojo.dto.FormDataAddDTO;
import com.xbongbong.paas.pojo.dto.FormDataListDTO;
import com.xbongbong.paas.pojo.dto.ImportFormDataDTO;
import com.xbongbong.paas.pojo.dto.ParseSingleRowDataDTO;
import com.xbongbong.paas.pojo.dto.SaasFormSaveDTO;
import com.xbongbong.paas.pojo.dto.UserAndDepartmentGetDTO;
import com.xbongbong.paas.pojo.dto.ValidateDataDTO;
import com.xbongbong.paas.pojo.imports.CellTitlePojo;
import com.xbongbong.paas.pojo.imports.CellValuePojo;
import com.xbongbong.paas.pojo.imports.RowGroupPojo;
import com.xbongbong.paas.pojo.vo.PaasFormDataEsListVO;
import com.xbongbong.paas.pojo.vo.ParseSingleRowDataVO;
import com.xbongbong.paas.pojo.vo.UserAndDepartmentGetVO;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.PageHelper;
import com.xbongbong.paas.toolbox.util.Arith;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.JsonHelperUtil;
import com.xbongbong.paas.toolbox.util.PageHelperUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.parent.parse.data.FormDataUpdateGetAnalysisDataHelp;
import com.xbongbong.pro.businessdata.pojo.dto.FormatExplainDTO;
import com.xbongbong.pro.businessproduct.pojo.dto.BusinessProductListDTO;
import com.xbongbong.pro.constant.BusinessConstant;
import com.xbongbong.pro.constant.ElasticConstant;
import com.xbongbong.pro.detailtab.pojo.OneKeyProduceProductPojo;
import com.xbongbong.pro.detailtab.vo.ProductSummaryVO;
import com.xbongbong.pro.domain.entity.FormConfigEntity;
import com.xbongbong.pro.domain.entity.LinkProductRelyEntity;
import com.xbongbong.pro.domain.entity.UpdateDataEntity;
import com.xbongbong.pro.enums.ReceiveStatusEnum;
import com.xbongbong.pro.enums.RefundStatusEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.AssembleErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.BuinessDefaultErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.ImportErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.InstockErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.OutstockErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.ProductErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SettleAccountErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.formexplain.pojo.dto.HandlerExplainDTO;
import com.xbongbong.pro.formexplain.pojo.dto.HandlerExplainInLinkItemDTO;
import com.xbongbong.pro.instock.pojo.dto.FormatInstockProductDTO;
import com.xbongbong.pro.instock.pojo.dto.InstockDeleteBatchDTO;
import com.xbongbong.pro.instock.pojo.dto.InstockEditAttrUpdateDTO;
import com.xbongbong.pro.instock.pojo.dto.InstockListDTO;
import com.xbongbong.pro.instock.pojo.dto.InstockUpdateBatchDTO;
import com.xbongbong.pro.instock.pojo.dto.InstockUpdateByBusinessRuleDTO;
import com.xbongbong.pro.instock.pojo.dto.InstockUpdateDTO;
import com.xbongbong.pro.instock.pojo.dto.RetMaterielListDTO;
import com.xbongbong.pro.instock.pojo.vo.InstockDeleteBatchVO;
import com.xbongbong.pro.instock.pojo.vo.InstockListVO;
import com.xbongbong.pro.instockproduct.pojo.dto.InstockProductDeleteBatchDTO;
import com.xbongbong.pro.instockproduct.pojo.dto.InstockProductListDTO;
import com.xbongbong.pro.instockproduct.pojo.vo.InstockProductDeleteBatchVO;
import com.xbongbong.pro.instockproduct.pojo.vo.InstockProductListVO;
import com.xbongbong.pro.inventory.pojo.dto.InventoryResetInstockIdDTO;
import com.xbongbong.pro.listbatch.pojo.dto.AddLabelDTO;
import com.xbongbong.pro.log.pojo.dto.RuleBusinessLogDTO;
import com.xbongbong.pro.product.pojo.dto.CostRecalculationDTO;
import com.xbongbong.pro.product.pojo.dto.PagingProductDTO;
import com.xbongbong.pro.product.pojo.dto.ProductListDTO;
import com.xbongbong.pro.product.pojo.vo.DetailProductVO;
import com.xbongbong.pro.product.pojo.vo.PagingProductVO;
import com.xbongbong.pro.product.pojo.vo.ProductListVO;
import com.xbongbong.pro.productionorder.pojo.dto.ProductionOrderListDTO;
import com.xbongbong.pro.productionorder.pojo.dto.ProductionOrderUpdateBatchDTO;
import com.xbongbong.pro.productionorder.pojo.dto.ProductionOrderUpdateDTO;
import com.xbongbong.pro.productionorder.pojo.vo.ProductionOrderListVO;
import com.xbongbong.pro.purchase.pojo.dto.PurchaseListDTO;
import com.xbongbong.pro.purchase.pojo.dto.PurchaseUpdateBatchDTO;
import com.xbongbong.pro.purchase.pojo.dto.PurchaseUpdateDTO;
import com.xbongbong.pro.purchase.pojo.vo.PurchaseListVO;
import com.xbongbong.pro.purchaseproduct.pojo.dto.PurchaseProductListDTO;
import com.xbongbong.pro.purchaseproduct.pojo.vo.PurchaseProductListVO;
import com.xbongbong.pro.rabbitmq.producer.CostRecalculationProducer;
import com.xbongbong.pro.refund.pojo.dto.RefundUpdateBatchDTO;
import com.xbongbong.pro.refund.pojo.dto.RefundUpdateDTO;
import com.xbongbong.pro.statistic.result.pojo.ElasticAggsPojo;
import com.xbongbong.pro.thread.ThreadPoolBeanConfig;
import com.xbongbong.pro.transfer.pojo.dto.TransferResetInstockIdDTO;
import com.xbongbong.pro.warehouse.pojo.dto.ProductWarehouseMapDTO;
import com.xbongbong.pro.warehouse.pojo.vo.ProductWarehouseMapVO;
import com.xbongbong.saas.analytical.impl.InstockValidateAnalyticalServiceImpl;
import com.xbongbong.saas.annotation.BusinessTypeToServiceAnnotation;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ErrorMessageConstant;
import com.xbongbong.saas.constant.MultiUnitConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.ProductConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.BatchFlowBillUpdateEntity;
import com.xbongbong.saas.domain.entity.BusinessProductEntity;
import com.xbongbong.saas.domain.entity.ContractProductEntity;
import com.xbongbong.saas.domain.entity.InstockProductEntity;
import com.xbongbong.saas.domain.entity.OutstockProductEntity;
import com.xbongbong.saas.domain.entity.ProductStockEntity;
import com.xbongbong.saas.domain.entity.ProductStockUpdateEntity;
import com.xbongbong.saas.domain.entity.ProductWarehouseEntity;
import com.xbongbong.saas.domain.entity.PurchaseProductEntity;
import com.xbongbong.saas.domain.entity.SettleAccountsEntity;
import com.xbongbong.saas.domain.entity.SmartReplenishmentEntity;
import com.xbongbong.saas.domain.entity.StockFlowBillUpdateEntity;
import com.xbongbong.saas.domain.entity.ext.InstockEntityExt;
import com.xbongbong.saas.domain.entity.ext.InstockProductEntityExt;
import com.xbongbong.saas.domain.entity.ext.ProductEntityExt;
import com.xbongbong.saas.domain.entity.ext.ProductionOrderEntityExt;
import com.xbongbong.saas.domain.entity.ext.PurchaseEntityExt;
import com.xbongbong.saas.domain.entity.ext.WarehouseEntityExt;
import com.xbongbong.saas.enums.BusinessProductEnum;
import com.xbongbong.saas.enums.BusinessTypeToServiceEnum;
import com.xbongbong.saas.enums.CompanyConfigEnum;
import com.xbongbong.saas.enums.FormConfigEnum;
import com.xbongbong.saas.enums.InstockTypeEnum;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.OutstockTypeEnum;
import com.xbongbong.saas.enums.RedundantTemplateTypeEnum;
import com.xbongbong.saas.enums.RelativeProductEnum;
import com.xbongbong.saas.enums.SelectProductEnum;
import com.xbongbong.saas.enums.StockTypeEnum;
import com.xbongbong.saas.enums.UpdateDataTypeEnum;
import com.xbongbong.saas.enums.WorkFlowEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.AssembleEnum;
import com.xbongbong.saas.enums.business.InstockEnum;
import com.xbongbong.saas.enums.business.InventoryEnum;
import com.xbongbong.saas.enums.business.OutstockEnum;
import com.xbongbong.saas.enums.business.ProductEnum;
import com.xbongbong.saas.enums.business.ProductionOrderEnum;
import com.xbongbong.saas.enums.business.PurchaseEnum;
import com.xbongbong.saas.enums.business.PurchaseInstockEnum;
import com.xbongbong.saas.enums.business.RefundEnum;
import com.xbongbong.saas.enums.business.RefundInstockEnum;
import com.xbongbong.saas.enums.business.ReturnedPurchaseEnum;
import com.xbongbong.saas.enums.business.TransferEnum;
import com.xbongbong.saas.enums.business.WarehouseEnum;
import com.xbongbong.saas.enums.dictionary.PurchaseStatusEnum;
import com.xbongbong.saas.enums.dictionary.WarehouseOriStockEnum;
import com.xbongbong.saas.enums.product.InstockProductEnum;
import com.xbongbong.saas.enums.product.RefundInstockProductEnum;
import com.xbongbong.saas.enums.subform.ProductStockSubFormEnum;
import com.xbongbong.saas.enums.subform.ProductWarehouseSubFormEnum;
import com.xbongbong.saas.help.BatchSeqExplainHelp;
import com.xbongbong.saas.help.ExplainHelp;
import com.xbongbong.saas.help.ImportHelper;
import com.xbongbong.saas.help.LogHandleHelp;
import com.xbongbong.saas.help.RelativeProductHelp;
import com.xbongbong.saas.help.SaasDeleteHelp;
import com.xbongbong.saas.help.SaasInstockHelp;
import com.xbongbong.saas.help.SaasSaveHelp;
import com.xbongbong.saas.help.SaasUpdateHelp;
import com.xbongbong.saas.help.workflow.InstockHelp;
import com.xbongbong.saas.help.workflow.ProductValidateHelp;
import com.xbongbong.saas.model.ContractProductModel;
import com.xbongbong.saas.model.FormConfigModel;
import com.xbongbong.saas.model.InstockModel;
import com.xbongbong.saas.model.InstockProductModel;
import com.xbongbong.saas.model.LinkProductRelyModel;
import com.xbongbong.saas.model.OutstockProductModel;
import com.xbongbong.saas.model.ProductModel;
import com.xbongbong.saas.model.ProductSerialFlowModel;
import com.xbongbong.saas.model.ProductStockModel;
import com.xbongbong.saas.model.ProductWarehouseModel;
import com.xbongbong.saas.model.PurchaseModel;
import com.xbongbong.saas.model.PurchaseProductModel;
import com.xbongbong.saas.model.RefundModel;
import com.xbongbong.saas.model.SettleAccountsModel;
import com.xbongbong.saas.model.SmartReplenishmentModel;
import com.xbongbong.saas.model.SpecificationModel;
import com.xbongbong.saas.model.WarehouseModel;
import com.xbongbong.saas.service.BusinessProductService;
import com.xbongbong.saas.service.FormatSpecialBusinessService;
import com.xbongbong.saas.service.InstockProductService;
import com.xbongbong.saas.service.InstockService;
import com.xbongbong.saas.service.InventoryService;
import com.xbongbong.saas.service.OriStockService;
import com.xbongbong.saas.service.ProductSerialService;
import com.xbongbong.saas.service.ProductService;
import com.xbongbong.saas.service.ProductionOrderService;
import com.xbongbong.saas.service.PurchaseProductService;
import com.xbongbong.saas.service.PurchaseService;
import com.xbongbong.saas.service.RefundService;
import com.xbongbong.saas.service.TransferService;
import com.xbongbong.saas.service.UserTeamService;
import com.xbongbong.saas.service.WarehouseService;
import com.xbongbong.saas.service.toolbox.help.AttrDecimalPrecisionHelper;
import com.xbongbong.saas.service.toolbox.help.LogHelp;
import com.xbongbong.saas.service.toolbox.help.ProductHelp;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import com.xbongbong.sys.domain.entity.DepartmentEntity;
import com.xbongbong.sys.domain.entity.UserEntity;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import static com.xbongbong.paas.elasticsearch.constant.EsNormalConstant.MINI_MUM_SHOULD_MATCH;
import static com.xbongbong.saas.enums.RelativeProductEnum.BARCODE;
import static com.xbongbong.saas.enums.RelativeProductEnum.BATCH;
import static com.xbongbong.saas.enums.RelativeProductEnum.COST;
import static com.xbongbong.saas.enums.RelativeProductEnum.GUARANTEE_PERIOD;
import static com.xbongbong.saas.enums.RelativeProductEnum.MEMO;
import static com.xbongbong.saas.enums.RelativeProductEnum.NAME;
import static com.xbongbong.saas.enums.RelativeProductEnum.NUM;
import static com.xbongbong.saas.enums.RelativeProductEnum.PRODUCE_DATE;
import static com.xbongbong.saas.enums.RelativeProductEnum.PRODUCT_NO;
import static com.xbongbong.saas.enums.RelativeProductEnum.SPECIFICATION;
import static com.xbongbong.saas.enums.RelativeProductEnum.STOCK;
import static com.xbongbong.saas.enums.RelativeProductEnum.UNIT;
import static com.xbongbong.saas.enums.RelativeProductEnum.WAREHOUSE;
import static com.xbongbong.saas.toolbox.help.FastJsonHelper.getDoubleOrDefaultFromFormData;
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.rangeQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;

/**
 * 入库单service实现层
 *
 * @author Jian.Wang
 * @version v1.0
 * @date 2019-02-21 12:23
 * @since v1.0
 **/
@Service("InstockService")
@BusinessTypeToServiceAnnotation(businessService = BusinessTypeToServiceEnum.INSTOCK)
public class InstockServiceImpl implements InstockService, FormatSpecialBusinessService {

    private static final Logger LOG = LoggerFactory.getLogger(InstockServiceImpl.class);

    @Resource
    private SaasUpdateHelp saasUpdateHelp;
    @Resource
    private ExplainHelp explainHelp;
    @Resource
    private ProductModel productModel;
    @Resource
    private PurchaseModel purchaseModel;
    @Resource
    private InstockProductModel instockProductModel;
    @Resource
    private PurchaseService purchaseService;
    @Resource
    private InstockModel instockModel;
    @Resource
    private InstockProductService instockProductService;
    @Resource
    private InventoryService inventoryService;
    @Resource
    private TransferService transferService;
    @Resource
    private ProductionOrderService productionOrderService;
    @Resource
    private WarehouseModel warehouseModel;
    @Resource
    private ProductService productService;
    @Resource
    private SaasSaveHelp saasSaveHelp;
    @Resource
    private PurchaseProductService purchaseProductService;
    @Resource
    private EsHelper esHelper;
    @Resource
    private CostRecalculationProducer costRecalculationProducer;
    @Resource
    private SpecificationModel specificationModel;
    @Resource
    private ProductWarehouseModel productWarehouseModel;
    @Resource
    private WarehouseService warehouseService;
    @Resource
    private ProductHelp productHelp;
    @Resource
    private BusinessProductService businessProductService;
    @Resource
    private RefundModel refundModel;
    @Resource
    private ContractProductModel contractProductModel;
    @Resource
    private RefundService refundService;
    @Resource
    private ImportHelper importHelper;
    @Resource
    private PaasProcessTemplateModel paasProcessTemplateModel;
    @Resource
    private ThreadPoolBeanConfig threadPoolBeanConfig;
    @Resource
    private MongoLogHelp mongoLogHelp;
    @Resource
    private UserTeamService userTeamService;
    @Resource
    private FormConfigModel formConfigModel;
    @Resource
    @Lazy
    private RuleBusinessLogger ruleBusinessLogger;
    @Resource
    private FormDataValidateProductHelp formDataValidateProductHelp;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private ProductStockModel productStockModel;
    @Resource
    private PaasEsModel paasEsModel;
    @Resource
    private PurchaseProductModel purchaseProductModel;
    @Resource
    private XbbElasticsearchRestTemplate xbbElasticsearchRestTemplate;
    @Resource
    private PaasRedisHelper paasRedisHelper;
    @Resource
    private LinkProductRelyModel linkProductRelyModel;
    @Resource
    private ProFormHelp proFormHelp;
    @Resource
    private FormDataUpdateGetAnalysisDataHelp formDataUpdateGetAnalysisDataHelp;
    @Resource
    private UserHelp userHelp;
    @Resource
    private SaasDeleteHelp saasDeleteHelp;
    @Resource
    private ProductSerialService productSerialService;
    @Resource
    private OutstockProductModel outstockProductModel;
    @Resource
    private OriStockService oriStockService;
    @Resource
    private AttrDecimalPrecisionHelper attrDecimalPrecisionHelper;
    @Resource
    private TransferSubFormHelper transferSubFormHelper;
    @Resource
    private PaasProcessRelatedDataModel paasProcessRelatedDataModel;
    @Resource
    private RelativeProductHelp relativeProductHelp;
    @Resource
    private LogHelp logHelp;
    @Resource
    private LogHandleHelp logHandleHelp;
    @Resource
    private InstockValidateAnalyticalServiceImpl instockAnalyticalService;
    @Resource
    private InstockHelp instockHelp;
    @Resource
    private SaasInstockHelp saasInstockHelp;
    @Resource
    private CommonHelp commonHelp;
    @Resource
    private SmartReplenishmentModel smartReplenishmentModel;
    @Resource
    private SettleAccountsModel settleAccountsModel;
    @Resource
    private ConcurrentLockAspect concurrentLockAspect;
    @Resource
    private ProductSerialFlowModel productSerialFlowModel;
    @Resource
    private ProductValidateHelp productValidateHelp;

    /**
     * 入库单保存前saas特殊校验
     *
     * @param validateDataDTO saas特殊校验数据入参
     * @throws XbbException 业务异常
     * @author feng.zheng
     * @date 2019/1/18
     */
    @Override
    public void beforeSave(ValidateDataDTO validateDataDTO) throws XbbException {
        instockAnalyticalService.beforeSave(validateDataDTO);
    }




    /**
     * 入库单保存后逻辑
     *
     * @param saasFormSaveDTO saas保存数据
     * @throws XbbException 业务异常
     * @author feng.zheng
     */
    @Override
    public void afterSave(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
        if (saasFormSaveDTO.getIsNew()) {
            // 逻辑改为仅新建进行入库单保存后逻辑：产品保存，库存更新，上游单据更新
            JSONObject data = saasFormSaveDTO.getNewData();
            String corpid = saasFormSaveDTO.getCorpid();
            JSONArray productJsonArray = data.getJSONArray(InstockEnum.PRODUCT.getAttr());
            String productStr = productJsonArray.toJSONString();
            PaasFormDataEntity newEntity = saasFormSaveDTO.getNewPaasFormDataEntity();
            Long instockId = newEntity.getId();
            Integer type = data.getInteger(InstockEnum.TYPE.getAttr());
            Long refId = Objects.isNull(data.getLong(InstockEnum.REF_ID.getAttr())) ? 0L : data.getLong(InstockEnum.REF_ID.getAttr());
            Long formId = saasFormSaveDTO.getNewPaasFormDataEntity().getFormId();
            saveProduct(productJsonArray, corpid, instockId,type,refId,formId, false);
            // 序列号入库
            productSerialService.saveSerial(saasFormSaveDTO, productStr);
            // 更改关联单据状态
            setIntstockDoucmentsNew(saasFormSaveDTO);
            //发送重算参数
            SaasFormSaveDTO saasFormSaveDTOCost = new SaasFormSaveDTO();
            saasFormSaveDTOCost.setCorpid(saasFormSaveDTO.getCorpid());
            saasFormSaveDTOCost.setBusinessType(saasFormSaveDTO.getBusinessType());
            saasFormSaveDTOCost.setNewData(saasFormSaveDTO.getNewData());
            saasFormSaveDTOCost.setNewPaasFormDataEntity(saasFormSaveDTO.getNewPaasFormDataEntity());
            CostRecalculationDTO costRecalculationDTO = new CostRecalculationDTO();
            costRecalculationDTO.setData(data);
            costRecalculationDTO.setMark(BasicConstant.ONE);
            costRecalculationDTO.setType(StockTypeEnum.IN_STOCK.getCode());
            costRecalculationDTO.setCorpid(corpid);
            costRecalculationDTO.setStockId(instockId);
            costRecalculationDTO.setIsWorkFlow(BasicConstant.ONE);
            costRecalculationDTO.setSaasFormSaveDTO(saasFormSaveDTOCost);
            //将流水放至重算方法中生成，保证处理的先后顺序
            /*stockFlowBillService.caculateStockModification4Save(saasFormSaveDTO);
            batchFlowBillService.batchFlowModification4Save(saasFormSaveDTO);*/
            costRecalculationProducer.sendMessage(costRecalculationDTO);
            // 退货入库单修复合同成本
            if(Objects.equals(type, InstockTypeEnum.RED_CONTRACT_INSTOCK.getCode())) {
                Set<Long> refIdSet = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                refIdSet.add(refId);
                instockHelp.afterSaveRefundInstock4ContractCost(corpid, refIdSet, saasFormSaveDTO.getIsNew(), productJsonArray);
            }
        }
    }


    private void setIntstockDoucmentsNew(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
        instockHelp.setIntstockDocumentsNew(saasFormSaveDTO.getCorpid(), saasFormSaveDTO.getNewData(), saasFormSaveDTO.getNewPaasFormDataEntity());
    }

    @Override
    public void saveProduct(JSONArray productArray, String corpid, Long instockId, Integer type, Long refId, Long formId, boolean isWorkflow) throws XbbException {
        //新增
        List<InstockProductEntity> addInstockProductEntityList = new ArrayList<>();
        Map<Long, PaasFormDataEntityExt> productMap = formDataValidateProductHelp.product2saveMap(corpid,productArray);
        Integer sort = 0;
        List<Long> warehouseIdList = new ArrayList<>();
        for (int i = 0; i < productArray.size(); i++) {
            JSONObject jsonObject = productArray.getJSONObject(i);
            // 移除序列号相关数据，不存入关联产品数据中
            jsonObject.remove(ProductConstant.SEQ);
            jsonObject.remove(ProductEnum.ENABLE_SERIAL_NUMBER.getSaasAttr());
            jsonObject.remove(ProductEnum.ENABLE_BATCH_SHELF_LIFE.getSaasAttr());

            Long pageProductId = jsonObject.getLong(SelectProductEnum.PRODUCT.getAttr());
            sort++;
            JSONObject productData = productMap.get(pageProductId).getData();
            InstockProductEntity entity = new InstockProductEntity();
            entity.setCorpid(corpid);
            entity.setProductId(pageProductId);
            entity.setParentId(productData.getLong(ProductEnum.PARENT_ID.getAttr()));
            jsonObject.put(ProductEnum.PARENT_ID.getSaasAttr(), productData.getLong(ProductEnum.PARENT_ID.getAttr()));
            entity.setProductNo(productData.getString(ProductEnum.PRODUCT_NO.getAttr()));
            entity.setProductNum(jsonObject.getDouble(InstockProductEnum.NUM.getAttr()));
            entity.setIntoWarehouseId(instockId);
            entity.setOutstockNum(0D);
            if (Objects.nonNull(jsonObject.getLong(BusinessConstant.REF_PRODUCT_ID))) {
                entity.setRefProductId(jsonObject.getLong(BusinessConstant.REF_PRODUCT_ID));
            }
            saasSaveHelp.formatLinkBusiness4Save(jsonObject, InstockProductEnum.WAREHOUSE.getAttr(), "warehouseName", FieldTypeEnum.LINK_BUSINESS_SINGLE.getType());
            entity.setWarehouseId(jsonObject.getLong(InstockProductEnum.WAREHOUSE.getAttr()));
            entity.setWarehouseName(jsonObject.getString("warehouseName"));
            entity.setProductName(productData.getString(ProductEnum.NAME.getAttr()));
            entity.setProductSpecification(productData.getString(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr()));
            entity.setSort(sort);
            entity.setType(type);
            entity.setPrice(jsonObject.getDouble(SelectProductEnum.PRICE.getAttr()));
            entity.setRefId(refId);
            entity.setFormId(formId);
            entity.setMemo(jsonObject.getString(InstockProductEnum.MEMO.getAttr()));
            entity.setBatch(Objects.isNull(jsonObject.getString(InstockProductEnum.BATCH.getAttr())) ? "" : jsonObject.getString(InstockProductEnum.BATCH.getAttr()));
            Long guaranteePeriod = Objects.isNull(jsonObject.getLong(InstockProductEnum.GUARANTEE_PERIOD.getAttr())) ? 0L : jsonObject.getLong(InstockProductEnum.GUARANTEE_PERIOD.getAttr()) * TimeConstant.SECONDS_PER_DAY;
            entity.setGuaranteePeriod(guaranteePeriod);
            Long produceDate = Objects.isNull(jsonObject.getLong(InstockProductEnum.PRODUCE_DATE.getAttr())) ? 0L : jsonObject.getLong(InstockProductEnum.PRODUCE_DATE.getAttr());
            entity.setProduceDate(produceDate);
            entity.setCost(Objects.isNull(jsonObject.getDouble(InstockProductEnum.COST.getAttr())) ? 0D : jsonObject.getDouble(InstockProductEnum.COST.getAttr()));
            jsonObject.put(InstockProductEnum.TOTAL_COST.getAttr(), Arith.mul(entity.getCost(), entity.getProductNum()));
            entity.setData(jsonObject);
            if (Objects.nonNull(entity.getWarehouseId())) {
                warehouseIdList.add(entity.getWarehouseId());
            }
            Integer enableMultiUnit = productData.getInteger(ProductEnum.ENABLE_MULTI_UNIT.getAttr());
            if (Objects.equals(enableMultiUnit, 1)) {
                formDataValidateProductHelp.setBusinessUnit(jsonObject, entity);
                entity.setProductUnit(jsonObject.getString(SelectProductEnum.UNIT.getAttr()));
            } else {
                entity.setProductUnit(productData.getString(ProductEnum.UNIT.getAttr()));
                jsonObject.put(InstockProductEnum.UNIT.getAttr(),productData.getString(ProductEnum.UNIT.getAttr()));
            }
            addInstockProductEntityList.add(entity);
        }

        if (!addInstockProductEntityList.isEmpty()){
            instockProductModel.insertBatch(addInstockProductEntityList);
            // 流水台账需要，工作流需要用
            for (int i = 0; i < productArray.size(); i++) {
                JSONObject jsonObject = productArray.getJSONObject(i);
                jsonObject.put(BusinessConstant.PRODUCT_SUB_ID, addInstockProductEntityList.get(i).getId());
            }
            // 采购入库处理智能补货数据
            if (Objects.equals(InstockTypeEnum.PURCHASE_INSTOCK.getCode(),type)){
                Map<Long,Double> smartProductMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                List<Long> productIdList = new ArrayList<>();
                for (InstockProductEntity entity : addInstockProductEntityList) {
                    Long productId = entity.getProductId();
                    Double productNum = entity.getProductNum();
                    if (smartProductMap.containsKey(productId)){
                        smartProductMap.put(productId,Arith.add(smartProductMap.get(productId),productNum));
                    }else {
                        smartProductMap.put(productId,productNum);
                        productIdList.add(productId);
                    }
                }
                if (CollectionsUtil.isNotEmpty(productIdList)){
                    List<SmartReplenishmentEntity> smartReplenishmentEntities = smartReplenishmentModel.getByProductList(corpid, productIdList);
                    if (CollectionsUtil.isNotEmpty(smartReplenishmentEntities)){
                        for (SmartReplenishmentEntity entity : smartReplenishmentEntities) {
                            Long productId = entity.getProductId();
                            if (smartProductMap.containsKey(productId)){
                                Double pendingInstockNum = Objects.isNull(entity.getPendingInstockNum()) ? 0D:entity.getPendingInstockNum();
                                Double instockNum = smartProductMap.getOrDefault(productId, 0D);
                                entity.setPendingInstockNum(Arith.sub(pendingInstockNum,instockNum) >= 0D ? Arith.sub(pendingInstockNum,instockNum) : 0D);
                            }
                        }
                        try {
                            smartReplenishmentModel.updateBatch(smartReplenishmentEntities,corpid);
                        }catch (Exception e){
                            LOG.error("instockServiceImpl.saveProduct() 更新智能补货表数据时出错", e);
                            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
                        }
                    }

                }
            }
        }

        if (!isWorkflow) {
            Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            params.put(ParameterConstant.CORPID,corpid);
            params.put(ParameterConstant.ID_IN,warehouseIdList);
            params.put(ParameterConstant.DEL,DelEnum.NORMAL.getDel());
            List<WarehouseEntityExt> warehouseEntityExts = warehouseModel.findEntitys(params);
            if (CollectionsUtil.isNotEmpty(warehouseEntityExts)){
                List<UpdateDataEntity> updateDataEntities = new ArrayList<>();
                for(WarehouseEntityExt warehouseEntityExt : warehouseEntityExts){
                    if (Objects.nonNull(warehouseEntityExt.getData()) && !Objects.equals(warehouseEntityExt.getData().getString(WarehouseEnum.ORI_STOCK.getAttr()), WarehouseOriStockEnum.NO_NEED.getCode())) {
                        JSONObject updateData = new JSONObject();
                        updateData.put(WarehouseEnum.ORI_STOCK.getAttr(), WarehouseOriStockEnum.NO_NEED.getCode());
                        updateDataEntities.add(ExplainUtil.getUpdateData(warehouseEntityExt.getId(), updateData, corpid));
                    }
                }
                if (!updateDataEntities.isEmpty()) {
                    warehouseModel.updateBatchImmediately(updateDataEntities, corpid);
                }
            }


            // 更新入库单产品的分仓库存、批次库存
            instockProductService.addUpdateStock(addInstockProductEntityList,corpid,false);
        }

//        productService.updateProductStockDown(warehouseMap, childProductIdList,productAddMap,corpid,true, false);
    }

    @Override
    public InstockListVO findInstockList(InstockListDTO instockListDTO) throws XbbException {
        InstockListVO instockListVO = new InstockListVO();
        try {
            BoolQueryBuilder boolQueryBuilder = boolQuery();
            String esData = StringConstant.JSON_DATA + StringConstant.POINT;
            if (Objects.nonNull(instockListDTO.getRefIdIn()) && !instockListDTO.getRefIdIn().isEmpty()) {
                boolQueryBuilder.filter(termsQuery(esData + InstockEnum.REF_ID.getAttr(), instockListDTO.getRefIdIn()));
            }
            if (Objects.nonNull(instockListDTO.getType())) {
                boolQueryBuilder.filter(termQuery(esData + InstockEnum.TYPE.getAttr(), instockListDTO.getType()));
            }
            if (Objects.nonNull(instockListDTO.getFlowStatusIn()) && !instockListDTO.getFlowStatusIn().isEmpty()) {
                boolQueryBuilder.filter(termsQuery(FieldTypeEnum.FLOW_STATUS.getAlias(), instockListDTO.getFlowStatusIn()));
            }
            boolQueryBuilder.filter(termQuery(StringConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, instockListDTO.getCorpid()));
            boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
            List<Long> delInstockIdList = instockListDTO.getMustNotIdIn();
            if (delInstockIdList != null && delInstockIdList.size() > 0) {
                boolQueryBuilder.mustNot(termsQuery(FieldTypeEnum.DATAID.getAlias(), delInstockIdList));
            }

            List<PaasFormDataEntityExt> instockList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_INSTOCK, boolQueryBuilder, PaasFormDataEntityExt.class, instockListDTO.getFieldList());
            if (Objects.isNull(instockList)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            instockListVO.setInstockList(instockList);

        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("instockServiceImpl.findInstockList 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return instockListVO;
    }

    @Override
    public PagingProductVO getPagingProduct(PagingProductDTO pagingProductDTO) throws XbbException {
        PagingProductVO pagingProductVO = new PagingProductVO();
        Map<String, Object> modelMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        modelMap.put(ParameterConstant.CORPID, pagingProductDTO.getCorpid());
        modelMap.put(ParameterConstant.INTO_WAREHOUSE_ID, pagingProductDTO.getDataId());
        modelMap.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        modelMap.put(ParameterConstant.PAGE,  pagingProductDTO.getPage());
        modelMap.put(ParameterConstant.ORDER_BY_STR, BasicConstant.SORT);
        PageHelper pageHelper = PageHelperUtil.getPageHelper(modelMap, instockProductModel, pagingProductDTO.getPageSize());
        List<InstockProductEntity> instockProductEntityList = (List<InstockProductEntity>) PageHelperUtil.getEntityList(modelMap, pageHelper, instockProductModel);
        if (pagingProductDTO.getUpdateDataTypeEnum().isDetail()) {
            DetailProductVO detailProductVO = formatProduct4DetailShow(instockProductEntityList, pagingProductDTO);
            pagingProductVO.setProductDataArr(detailProductVO.getProductDataArr());
        }
        pagingProductVO.setPageHelper(pageHelper);
        return pagingProductVO;
    }

    public DetailProductVO formatProduct4DetailShow(List<InstockProductEntity> instockProductEntityList, PagingProductDTO pagingProductDTO) throws XbbException{
        DetailProductVO detailProductVO = new DetailProductVO();
        Set<Long> productIds = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<Long> warehouseIdList = new ArrayList<>();
        List<String> batchKeyList = new ArrayList<>();
        Set<String> warehouseKeySet = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (InstockProductEntity instockProductEntity : instockProductEntityList) {
            productIds.add(instockProductEntity.getProductId());
            warehouseIdList.add(instockProductEntity.getWarehouseId());
            if (StringUtil.isNotEmpty(instockProductEntity.getBatch())) {
                String key = formDataValidateProductHelp.getBatchKey(instockProductEntity.getProductId(), instockProductEntity.getWarehouseId(), instockProductEntity.getBatch(), instockProductEntity.getProduceDate(), instockProductEntity.getGuaranteePeriod());
                batchKeyList.add(key);
            }
            warehouseKeySet.add(instockProductEntity.getProductId() + "_" + instockProductEntity.getWarehouseId());
        }
        List<PaasFormDataEntityExt> warehouseList = paasEsModel.getByIdList(warehouseIdList, pagingProductDTO.getCorpid(), SaasMarkEnum.SAAS.getCode(), XbbRefTypeEnum.WAREHOUSE.getCode(), new ArrayList<>(), IndexTypeEnum.IDX_SAAS_WAREHOUSE);
        Map<Long, String> warehouseNameMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (PaasFormDataEntityExt paasFormDataEntityExt : warehouseList) {
            JSONObject data = paasFormDataEntityExt.getData();
            warehouseNameMap.put(paasFormDataEntityExt.getId(), FastJsonHelper.getStringOrDefaultFromFormData(data, WarehouseEnum.WAREHOUSE_NAME.getAttr(), ""));
        }
        String corpid = pagingProductDTO.getCorpid();
        JSONArray productArray = new JSONArray();
//        Map<Long, PaasFormDataEntityExt> productMap = productService.getProductMapByIdIn(productIds, corpid, DelEnum.NORMAL);
        //分仓库存
        Map<String, Double> productWarehouseMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (!productIds.isEmpty() && !warehouseIdList.isEmpty()) {
            Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            params.put("del", DelEnum.NORMAL.getDel());
            params.put(ParameterConstant.CORPID, corpid);
//            params.put("productIdIn", productIds);
//            params.put("warehouseIdIn", warehouseIdList);
            params.put("warehouseKeyIn",warehouseKeySet);
            List<ProductWarehouseEntity> productWarehouseEntities = productWarehouseModel.findEntitysWithWarehouseChecked(params,null);
            productWarehouseEntities.forEach(item -> {
                String key = item.getProductId() + "_" + item.getWarehouseId();
                productWarehouseMap.put(key, item.getNum());
            });
        }
        //批次库存
        if (!batchKeyList.isEmpty()) {
            Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            params.put("del", DelEnum.NORMAL.getDel());
            params.put(ParameterConstant.CORPID, corpid);
            params.put("batchKeyIn", batchKeyList);
            List<ProductStockEntity> productStockEntities = productStockModel.findEntitys(params);
            productStockEntities.forEach(item -> {
                productWarehouseMap.put(item.getBatchKey(), item.getNum());
            });
        }
        for (InstockProductEntity instockProductEntity : instockProductEntityList) {
            Double stock;
            if (StringUtil.isNotEmpty(instockProductEntity.getBatch())) {
                stock = productWarehouseMap.getOrDefault(formDataValidateProductHelp.getBatchKey(instockProductEntity.getProductId(), instockProductEntity.getWarehouseId(), instockProductEntity.getBatch(), instockProductEntity.getProduceDate(), instockProductEntity.getGuaranteePeriod()), 0D);
            } else {
                stock = productWarehouseMap.getOrDefault(instockProductEntity.getProductId() + "_" + instockProductEntity.getWarehouseId(), 0D);
            }
            JSONObject json = new JSONObject();
            if (Objects.nonNull(instockProductEntity.getData())) {
                json = instockProductEntity.getData();
            }
            if (Objects.nonNull(instockProductEntity.getBusinessUnit())) {
                instockProductEntity.setProductNum(Arith.div(instockProductEntity.getProductNum(), instockProductEntity.getRate()));
                instockProductEntity.setProductUnit(instockProductEntity.getBusinessUnit().toString());
                JSONObject priceData = instockProductEntity.getPriceData();
                if (Objects.nonNull(priceData) && !priceData.isEmpty()) {
                    instockProductEntity.setCost(priceData.getDouble(SelectProductEnum.COST.getAttr()));
                }
            }
            if (Objects.equals(pagingProductDTO.getBusinessType(), XbbRefTypeEnum.REFUND_INSTOCK.getCode())) {
                if (Objects.nonNull(instockProductEntity.getBusinessUnit()) && Objects.nonNull(instockProductEntity.getPriceData())) {
                    instockProductEntity.setPrice(instockProductEntity.getPriceData().getDouble(SelectProductEnum.PRICE.getAttr()));
                }
                json.put(SelectProductEnum.PRICE.getAttr(), instockProductEntity.getPrice());
                json.put(SelectProductEnum.SUBTOTAL.getAttr(), instockProductEntity.getPrice() * instockProductEntity.getProductNum());
            }
            for (InstockProductEnum instockProductEnum : InstockProductEnum.values()) {
                if (!UpdateDataTypeEnum.DETAIL.formatShow(instockProductEnum.getShowType())) {
                    continue;
                }
                String attr = instockProductEnum.getAttr();
                switch (instockProductEnum) {
                    case PRODUCT:
                        json.put(attr, instockProductEntity.getProductId());
                        break;
                    case WAREHOUSE:
                        JSONArray warehouseArr = productHelp.packegeLinkBusinessJsonArray(instockProductEntity.getWarehouseId(),
                                warehouseNameMap.getOrDefault(instockProductEntity.getWarehouseId(), ""), XbbRefTypeEnum.WAREHOUSE.getCode(), SaasMarkEnum.SAAS.getCode());
                        json.put(attr, warehouseArr);
                        break;
                    case NUM:
                        json.put(attr, instockProductEntity.getProductNum());
                        break;
                    case COST:
                        json.put(attr, instockProductEntity.getCost());
                        break;
                    case TOTAL_COST:
                        if (Objects.nonNull(instockProductEntity.getProductNum()) && Objects.nonNull(instockProductEntity.getCost())) {
                            json.put(attr, Arith.mul(instockProductEntity.getProductNum(), instockProductEntity.getCost()));
                        }
                        break;
                    case STOCK:
                        json.put(attr, stock);
                        break;
                    case MEMO:
                        json.put(attr, instockProductEntity.getMemo());
                        break;
                    case BATCH:
                        json.put(attr, instockProductEntity.getBatch());
                        break;
                   case PRODUCE_DATE:
                        if (Objects.nonNull(instockProductEntity.getProduceDate())) {
                            json.put(attr, instockProductEntity.getProduceDate());
                        }
                        break;
                    case GUARANTEE_PERIOD:
                        if (Objects.nonNull(instockProductEntity.getGuaranteePeriod()) && !Objects.equals(instockProductEntity.getProduceDate(), 0L)) {
                            json.put(attr, Arith.div(instockProductEntity.getGuaranteePeriod(), 86400D));
                        } else {
                            json.remove(attr);
                        }
                        break;
                    case EXPIRE_DATE:
                        if (Objects.nonNull(instockProductEntity.getGuaranteePeriod()) && Objects.nonNull(instockProductEntity.getProduceDate())) {
                            json.put(attr, Arith.add(instockProductEntity.getProduceDate(), instockProductEntity.getGuaranteePeriod()));
                        }
                        break;
                    case UNIT:
                        json.put(attr, instockProductEntity.getProductUnit());
                        break;
                    default:
                        break;
                }
            }
            json.put("refId",instockProductEntity.getId());
            json.put(BusinessConstant.PRODUCT_SUB_ID, instockProductEntity.getId());
            productArray.add(json);
        }
        detailProductVO.setProductDataArr(productArray);
        return detailProductVO;
    }

    @Override
    public void formatProduct4Show2(Long dataId, String corpid, JSONObject data, Boolean forProcess, Integer operate, UpdateDataTypeEnum updateDataTypeEnum) throws XbbException {
        instockModel.formatProduct4Show2(dataId, corpid, data, forProcess, operate, updateDataTypeEnum);
    }

    @Override
    public JSONObject formatSingleProduct(InstockProductEntity instockProductEntity) {
        return instockModel.formatSingleProduct(instockProductEntity);
    }

    @Override
    public void generateInStockSheet(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
        PaasFormDataEntity newPaasFormDataEntity = saasFormSaveDTO.getNewPaasFormDataEntity();
        Long refId = newPaasFormDataEntity.getId();
        String corpid = saasFormSaveDTO.getCorpid();
        Integer businessType = saasFormSaveDTO.getBusinessType();
        String instockType = InstockTypeEnum.getByBuisenssType(businessType);
        JSONObject newData = saasFormSaveDTO.getNewData();
        Object time = newData.get(InventoryEnum.TIME.getAttr());
        String productAttr = null;
        if (Objects.equals(businessType, XbbRefTypeEnum.ASSEMBLE.getCode())) {
            productAttr = AssembleEnum.IN_PRODUCTS.getAttr();
        }else if (Objects.equals(businessType,XbbRefTypeEnum.TRANSFER.getCode())){
            productAttr = TransferEnum.PRODUCTS.getAttr();
        }else if (Objects.equals(businessType,XbbRefTypeEnum.INVENTORY.getCode())){
            productAttr = InventoryEnum.PRODUCT.getAttr();
        }
        JSONArray productArray = saasSaveHelp.formatSelectProduct4Save2(newData, productAttr);
        // 判断是否已经生成入库单
        Map<String, Object> modelMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        modelMap.put(ParameterConstant.CORPID, corpid);
        modelMap.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        Map<String, Object> dataParam = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        dataParam.put(InstockEnum.REF_ID.getAttr(), refId);
        dataParam.put(InstockEnum.TYPE.getAttr(), instockType);
        List<PaasFormDataEntityExt> paasFormDataEntityExts = paasEsModel.selectByCondition(XbbRefTypeEnum.INSTOCK.getCode(), dataParam, modelMap, IndexTypeEnum.IDX_SAAS_INSTOCK);
        PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByBusinessType(XbbRefTypeEnum.OTHER_INSTOCK.getCode(), corpid);
        if (Objects.isNull(paasFormExplainEntity)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_EXPLAIN_NOT_EXIST);
        }
        // 获取字段解释信息
        List<FieldAttrEntity> explainList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
        FieldAttrEntity linkProductField = new FieldAttrEntity();
        for (FieldAttrEntity fieldAttrEntity : explainList) {
            if (OutstockEnum.PRODUCT.getAttr().equals(fieldAttrEntity.getAttr())) {
                linkProductField = fieldAttrEntity;
                break;
            }
        }
        InstockEntityExt instock = new InstockEntityExt();
        if (paasFormDataEntityExts.isEmpty()) {
            instock.setCorpid(corpid);
            BeanUtil.copyProperties(paasFormExplainEntity, instock);
            Map<String, FieldAttrEntity> explainMap = ExplainUtil.getExplainMap(paasFormExplainEntity.getExplains(), null);
            // 获取流水号
            String serialNo = saasSaveHelp.getSerialNo(explainList, paasFormExplainEntity.getFormId(), corpid);
            instock.setSerialNo(serialNo);
            instock.setOwnerId(newPaasFormDataEntity.getOwnerId());
            instock.setDepartmentId(0L);
            instock.setFlowStatus(FlowStatusEnum.NOT_NEED_APPROVAL.getType());
            instock.setCreatorId(newPaasFormDataEntity.getCreatorId());
            JSONObject instockData = new JSONObject();
            //公共的部分
            if (explainMap.containsKey(InstockEnum.TIME.getAttr())) {
                String dateType = explainMap.get(InstockEnum.TIME.getAttr()).getDateType();
                if (Objects.nonNull(time) && !Objects.equals(XbbRefTypeEnum.INVENTORY.getCode(),businessType)){
                    instockData.put(OutstockEnum.TIME.getAttr(), Long.valueOf(time.toString()));
                }else {
                    instockData.put(InstockEnum.TIME.getAttr(), DateTimeUtil.getThisIntByDateType(dateType));
                }
            } else {
                if (Objects.nonNull(time) && !Objects.equals(XbbRefTypeEnum.INVENTORY.getCode(),businessType)){
                    instockData.put(OutstockEnum.TIME.getAttr(), Long.valueOf(time.toString()));
                }else {
                    instockData.put(InstockEnum.TIME.getAttr(), DateTimeUtil.getTodayInt());
                }
            }
            instockData.put(InstockEnum.TYPE.getAttr(), instockType);
            instockData.put(InstockEnum.REF_ID.getAttr(), refId);
            instockData.put(InstockEnum.REF_ID_LINKED_TEXT.getAttr(), newPaasFormDataEntity.getSerialNo());
            instockData.put(InstockEnum.INCOMING.getAttr(), BasicConstant.ONE);
            //特殊的部分
            formatInstockData(instockData, newData, businessType, productArray, saasFormSaveDTO.getCostMap(), corpid);
            instock.setId(null);
            instock.setData(instockData);
            instockModel.save(instock);
        } else {
            PaasFormDataEntityExt paasFormDataEntityExt = paasFormDataEntityExts.get(BasicConstant.ZERO);
            BeanUtil.copyProperties(paasFormDataEntityExt, instock);
        }

        // 数据联动
        // 数据联动
        DefaultAttrPoJo defaultAttr = linkProductField.getDefaultAttr();
        String defaultType = defaultAttr.getDefaultType();
        // 获取关联产品联动关系
        LinkProductRelyEntity linkProductRelyEntity = linkProductRelyModel.getByAttrAndFormIdAndSourceBusinessType(corpid, InstockEnum.PRODUCT.getAttr(), paasFormExplainEntity.getFormId(), businessType, DelEnum.NORMAL.getDel());
        if (Objects.nonNull(defaultType) && DefaultTypeEnum.PRODUCT_DATA_RELY.getAlias().equals(defaultType) && Objects.nonNull(linkProductRelyEntity)) {
            // 源单解释
            Map<String, FieldAttrEntity> sourceExplainMap;
            // 当前表单解释
            Map<String, FieldAttrEntity> thisExplainMap;
            // 当前表单某个关联产品解释
            Map<String, FieldAttrEntity> subThisExplainMap;
            // 源单某个关联产品解释
            Map<String, FieldAttrEntity> subSourceExplainMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            // 当前表单某个关联产品子字段与源单某个关联产品对应关系
            Map<String, String> thisToTarget = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            // 源数据表单
            PaasFormExplainEntity sourcePaasFormExplainEntity = proFormHelp.getExplainEntity(corpid, linkProductRelyEntity.getSourceFormId(), linkProductRelyEntity.getSourceBusinessType());
            List<FieldAttrEntity> sourceExplainList = JSONArray.parseArray(sourcePaasFormExplainEntity.getExplains(), FieldAttrEntity.class);
            sourceExplainMap = ExplainUtil.getExplainMapByList(sourceExplainList, null);
            // 当前表单
            thisExplainMap = ExplainUtil.getExplainMap(paasFormExplainEntity.getExplains(), null);
            subThisExplainMap = businessProductService.getProductRelyMap(InstockEnum.PRODUCT.getAttr(), linkProductRelyEntity, sourceExplainMap, thisExplainMap, subSourceExplainMap, thisToTarget);
            for (Object o : productArray) {
                JSONObject productData = (JSONObject) o;
                if (!thisToTarget.isEmpty()) {
                    JSONObject thisData = businessProductService.formatThisFormData(subThisExplainMap, thisToTarget, productData);
                    for (int i = 0; i < productArray.size(); i++) {
                        JSONObject jsonObject = productArray.getJSONObject(i);
                        if (Objects.equals(jsonObject.getLongValue(BusinessConstant.REF_PRODUCT_ID), productData.getLongValue(BusinessConstant.REF_PRODUCT_ID))) {
                            jsonObject.putAll(thisData);
                            break;
                        }
                    }
                }
            }
        }

        instock.getData().put(InstockEnum.PRODUCT.getAttr(),productArray);
        SaasFormSaveDTO instockSaasFormSaveDTO = new SaasFormSaveDTO();
        BeanUtil.copyProperties(saasFormSaveDTO,instockSaasFormSaveDTO);
        instockSaasFormSaveDTO.setNewData(instock.getData());
        instockSaasFormSaveDTO.setNewPaasFormDataEntity(instock);
        instockSaasFormSaveDTO.setBusinessType(XbbRefTypeEnum.OTHER_INSTOCK.getCode());
        afterSave(instockSaasFormSaveDTO);
    }

    /**
     * 自动生成入库单时格式化出库单保存时得数据
     * @param instockData 保存的数据
     * @param businessType
     * @param newData 前端传的数据
     */
    private void formatInstockData(JSONObject instockData,JSONObject newData ,Integer businessType,JSONArray productArray, Map<Object,Double> costMap, String corpid) throws XbbException {
        RedundantTemplateTypeEnum redundantTemplateTypeEnum = RedundantTemplateTypeEnum.getByCode(businessType);
        switch (redundantTemplateTypeEnum){
            case TRANSFER:
                instockData.put(InstockEnum.WAREHOUSE_ID.getAttr(), FastJsonHelper.getLongOrDefaultFromFormData(newData, TransferEnum.INTO_WAREHOUSE_ID.getAttr(), 0L));
                instockData.put(InstockEnum.WAREHOUSE_ID_LINKED_TEXT.getAttr(), FastJsonHelper.getStringOrDefaultFromFormData(newData, TransferEnum.INTO_WAREHOUSE_ID_LINKED_TEXT.getAttr(), ""));
                instockData.put(InstockEnum.MEMO.getAttr(), FastJsonHelper.getStringOrDefaultFromFormData(newData, TransferEnum.MEMO.getAttr(), ""));
                instockData.put(InstockEnum.PRODUCT.getAttr(), newData.getJSONArray(TransferEnum.PRODUCTS.getAttr()));

                Long refId = instockData.getLong(InstockEnum.REF_ID.getAttr());
                Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                param.put(ParameterConstant.CORPID, corpid);
                param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
                param.put("refId", refId);
                param.put("type", OutstockTypeEnum.TRANSFER_OUTSTOCK.getCode());
                List<OutstockProductEntity> entitys = outstockProductModel.findEntitys(param);

                Map<Long, Long> refProductMap = new HashMap<>();
                for (OutstockProductEntity entity : entitys) {
                    refProductMap.put(entity.getRefProductId(), entity.getId());
                    costMap.put(entity.getRefProductId(), entity.getCost());
                }
                for (int i = 0; i < productArray.size(); i++) {
                    JSONObject jsonObject = productArray.getJSONObject(i);
                    jsonObject.put(InstockProductEnum.WAREHOUSE.getAttr(), FastJsonHelper.getLongOrDefaultFromFormData(newData, InstockEnum.WAREHOUSE_ID.getAttr(), 0L));
                    jsonObject.put("warehouseName", FastJsonHelper.getStringOrDefaultFromFormData(newData, TransferEnum.INTO_WAREHOUSE_ID_LINKED_TEXT.getAttr(), ""));
                    jsonObject.put(SelectProductEnum.COST.getAttr(), costMap.getOrDefault(jsonObject.getLong(BusinessConstant.REF_PRODUCT_ID), 0D));
                    jsonObject.put(SelectProductEnum.TOTAL_COST.getAttr(), Arith.mul(jsonObject.getDouble(SelectProductEnum.COST.getAttr()), jsonObject.getDouble(SelectProductEnum.NUM.getAttr())));
                    jsonObject.put(BusinessConstant.REF_PRODUCT_ID, refProductMap.getOrDefault(jsonObject.getLong(BusinessConstant.REF_PRODUCT_ID), 0L));
                    Double rate = jsonObject.getDouble(SelectProductEnum.RATE.getAttr());
                    if (Objects.nonNull(rate)) {
                        jsonObject.put(SelectProductEnum.BUSINESS_COST.getAttr(), Arith.mul(jsonObject.getDouble(SelectProductEnum.COST.getAttr()), rate));
                    }
                }
                break;
            case ASSEMBLE:
                instockData.put(InstockEnum.WAREHOUSE_ID.getAttr(), FastJsonHelper.getLongOrDefaultFromFormData(newData, AssembleEnum.INTO_WAREHOUSE_ID.getAttr(), 0L));
                instockData.put(InstockEnum.WAREHOUSE_ID_LINKED_TEXT.getAttr(), FastJsonHelper.getStringOrDefaultFromFormData(newData, AssembleEnum.INTO_WAREHOUSE_ID_LINKED_TEXT.getAttr(), ""));
                instockData.put(InstockEnum.MEMO.getAttr(), FastJsonHelper.getStringOrDefaultFromFormData(newData, AssembleEnum.MEMO.getAttr(), ""));
                instockData.put(InstockEnum.PRODUCT.getAttr(), newData.getJSONArray(AssembleEnum.IN_PRODUCTS.getAttr()));
                break;
            case INVENTORY:
                instockData.put(InstockEnum.WAREHOUSE_ID.getAttr(), FastJsonHelper.getLongOrDefaultFromFormData(newData, InventoryEnum.WAREHOUSE_ID.getAttr(), 0L));
                instockData.put(InstockEnum.WAREHOUSE_ID_LINKED_TEXT.getAttr(), FastJsonHelper.getStringOrDefaultFromFormData(newData, InventoryEnum.WAREHOUSE_ID_LINKED_TEXT.getAttr(), ""));
                instockData.put(InstockEnum.MEMO.getAttr(), FastJsonHelper.getStringOrDefaultFromFormData(newData, InventoryEnum.MEMO.getAttr(), ""));
                instockData.put(InstockEnum.PRODUCT.getAttr(), newData.getJSONArray(InventoryEnum.PRODUCT.getAttr()));
                for (int i = 0; i < productArray.size(); i++) {
                    JSONObject jsonObject = productArray.getJSONObject(i);
                    jsonObject.put(InstockProductEnum.WAREHOUSE.getAttr(), FastJsonHelper.getLongOrDefaultFromFormData(newData, InstockEnum.WAREHOUSE_ID.getAttr(), 0L));
                    jsonObject.put("warehouseName", FastJsonHelper.getStringOrDefaultFromFormData(newData, InventoryEnum.WAREHOUSE_ID_LINKED_TEXT.getAttr(), ""));
                    if (StringUtil.isNotEmpty(jsonObject.getString(SelectProductEnum.BATCH.getAttr()))) {
                        jsonObject.put(SelectProductEnum.COST.getAttr(), costMap.getOrDefault(formDataValidateProductHelp.getBatchKey(jsonObject.getLong(SelectProductEnum.PRODUCT.getAttr()), jsonObject.getLong(SelectProductEnum.WAREHOUSE.getAttr()), jsonObject.getString(SelectProductEnum.BATCH.getAttr()), jsonObject.getLong(SelectProductEnum.PRODUCE_DATE.getAttr()), FastJsonHelper.getLongOrDefaultFromFormData(jsonObject, SelectProductEnum.GUARANTEE_PERIOD.getAttr(), 0L) * TimeConstant.SECONDS_PER_DAY), 0D));
                    }else {
                        jsonObject.put(SelectProductEnum.COST.getAttr(), costMap.getOrDefault(jsonObject.getLong(SelectProductEnum.PRODUCT.getAttr())+ "_" + jsonObject.get(InstockProductEnum.WAREHOUSE.getAttr()), 0D));
                    }
                    jsonObject.put(SelectProductEnum.TOTAL_COST.getAttr(), Arith.mul(jsonObject.getDouble(SelectProductEnum.COST.getAttr()), jsonObject.getDouble(SelectProductEnum.NUM.getAttr())));
                }
                break;
            default:
                break;
        }
    }
    /**
     * 获取入库单产品
     *
     * @return BusinessProductListVO，属性product包含了入库单关联产品，返回给前端的格式
     * @author chaoxiong.lei
     * @Date 14:37 2019/3/5
     * @since v1.0
     **/
    /*@Override
    public BusinessProductListVO getInstockProductList(BusinessProductListDTO businessProductListDTO, JSONObject jsonObject) throws XbbException {
        String corpid = businessProductListDTO.getCorpid();
        Long instockId = businessProductListDTO.getDataId();
        boolean detailGet = businessProductListDTO.getDetailGet();
        String userId = businessProductListDTO.getUserId();
        UserEntity userEntity = userModel.getByKey(userId, corpid);

        // 获取出库单关联产品
        List<InstockProductEntity> instockProductList = new ArrayList<>();
        List<ProductStockInfoEntity> productStockInfoList = new ArrayList<>();
        Map<String, Object> modelMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        modelMap.put(ParameterConstant.CORPID, corpid);
        modelMap.put("intoWarehouseId", instockId);
        modelMap.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        modelMap.put(ParameterConstant.PAGE, businessProductListDTO.getPage());
        PageHelper pageHelper = PageHelperUtil.getPageHelper(modelMap, instockProductModel, businessProductListDTO.getPageSize());
        if (jsonObject != null) {
            JSONArray productArray = FastJsonHelper.getJsonArrOrDefaultFromFormData(saasUpdateHelp.getJsonObjectOrDefaultFromFormData(jsonObject, InstockEnum.PRODUCT.getAttr(), new JSONObject()), StringConstant.PRODUCT_LIST, new JSONArray());
            Map<Long, ProductEntityExt> productMap = getProductMap(new HashSet<>(), corpid, productArray);
            getProductList(corpid, instockProductList, productStockInfoList, productArray, productMap);
        } else {
            instockProductList = (List<InstockProductEntity>)PageHelperUtil.getEntityList(modelMap, pageHelper, instockProductModel);
        }

        // 根据idIn参数获取对应的产品数据
        Set<Long> productIdIn = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        productIdIn.add(-1L);
        List<Long> instockProductIds = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        instockProductIds.add(-1L);
        List<Long> warehouseIds = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        warehouseIds.add(-1L);
        Set<String> warehouseKeySet = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (InstockProductEntity entity : instockProductList) {
            productIdIn.add(entity.getProductId());
            instockProductIds.add(entity.getId());
            warehouseIds.add(entity.getWarehouseId());
            warehouseKeySet.add(entity.getProductId() + "_" + entity.getWarehouseId());
        }

        // 入库单产品对应产品信息
        Map<Long, PaasFormDataEntityExt> productMap = productService.getProductMapByIdIn(productIdIn, corpid, DelEnum.NORMAL);

        // 入库单产品对应仓库信息
        Map<Long, JSONObject> warehouseMap = warehouseModel.findWarehouseObjMapByIdIn(warehouseIds, corpid);

        // 参数集合
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        params.put("corpid", corpid);
        params.put("del", 0);
//        params.put("productIdIn", productIdIn);
//        params.put("warehouseIdIn", warehouseIds);
        params.put("warehouseKeyIn",warehouseKeySet);
        List<ProductWarehouseEntity> productWarehouseEntityList = productWarehouseModel.findEntitysWithWarehouseChecked(params,null);


        // 用于存放当前启用的产品模板解释的map
        Map<String, FieldAttrEntity> nowProductExplainMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<String, FieldAttrEntity> nowStockProductExplainMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        saasAddHelp.getRelativeProductExplainsFromDB(corpid, nowProductExplainMap, nowStockProductExplainMap);

        JSONObject productFinalObj = new JSONObject();
        JSONArray productArray = new JSONArray();
        // 将产品存入map中，key为产品的sort值，用于产品排序
        Map<Integer, JSONObject> productSortMap = new TreeMap<>();
        BusinessProductListVO businessProductListVO = new BusinessProductListVO();
        // 与productList同级，返回对应关联产品的attr
        String attrStr = InstockEnum.PRODUCT.getAttr();

        for (InstockProductEntity instockProduct : instockProductList) {
            Long productId = instockProduct.getProductId();
            Long instockProductId = instockProduct.getId();
            Long warehouseId = instockProduct.getWarehouseId();

            InstockProductEntityExt instockProductExt = new InstockProductEntityExt();
            BeanUtil.copyProperties(instockProduct, instockProductExt);
            // 格式化规格
            String specification = specificationModel.joinSpecification(instockProduct.getProductSpecification());
            instockProductExt.setProductSpecification(specification);
            // 设置仓库信息
            if (warehouseId != null) {
                JSONObject warehouseObj = warehouseMap.get(warehouseId);
                instockProductExt.setWarehouseObj(warehouseObj);
            }

            Double productStock = 0.0;
            String batch;
            // 获取对应的产品信息
            PaasFormDataEntityExt product = productMap.get(productId);
            if (product != null) {
                JSONObject productDataList = product.getData();
                instockProductExt.setBarcode(productDataList.getString(ProductEnum.BARCODE.getAttr()));
                // 产品的总库存
                productStock = productDataList.getDouble(ProductEnum.STOCK.getAttr());
                instockProductExt.setImageUrlArray(productDataList.getJSONArray(ProductEnum.PRODUCT_IMGS.getAttr()));
            }

            for (ProductWarehouseEntity productWarehouseEntity : productWarehouseEntityList) {
                if (Objects.equals(productWarehouseEntity.getWarehouseId(), warehouseId) && Objects.equals(productWarehouseEntity.getProductId(), productId)) {
                    productStock = productWarehouseEntity.getNum();
                    break;
                }
            }

            // 设置库存信息
            instockProductExt.setStock(productStock);

            // 构建格式化入库产品的DTO
            FormatInstockProductDTO formatInstockProductDTO = new FormatInstockProductDTO();
            BeanUtil.copyProperties(businessProductListDTO, formatInstockProductDTO);
            formatInstockProductDTO.setCorpid(corpid);
            formatInstockProductDTO.setUserEntity(userEntity);
//            instockProductExt.setProductStockInfoEntity(productStockInfo);
            formatInstockProductDTO.setInstockProductExt(instockProductExt);
            formatInstockProductDTO.setNowProductExplainMap(nowProductExplainMap);
            formatInstockProductDTO.setNowStockProductExplainMap(nowStockProductExplainMap);
            JSONObject productObj = getFormatProductJsonArray(formatInstockProductDTO);

            productSortMap.put(instockProductExt.getSort(), productObj);
        }
        // 产品排序
        productArray.addAll(productSortMap.values());
        productFinalObj.put(StringConstant.PRODUCT_LIST, productArray);
        productFinalObj.put(StringConstant.REDUNDANT_FIELD_ATTR_BEGIN_FLAG, attrStr);
        if (detailGet) {
            productFinalObj.put(BusinessConstant.EXPLAINS, saasUpdateHelp.getSelectProductExplains(XbbRefTypeEnum.INSTOCK, corpid, InstockEnum.PRODUCT.getAttr()));
        }
        businessProductListVO.setProduct(productFinalObj);
        businessProductListVO.setPageHelper(pageHelper);
        return businessProductListVO;
    }*/

    @Override
    public void batchEditAttr(InstockEditAttrUpdateDTO instockEditAttrUpdateDTO) throws XbbException {
        try {
            List<InstockUpdateDTO> instockUpdateDTOS = new ArrayList<>();
            instockEditAttrUpdateDTO.getDataIdList().forEach((item) -> {
                InstockUpdateDTO outstockUpdateDTO = new InstockUpdateDTO();
                outstockUpdateDTO.setId(item);
                JSONObject data = ProSaveHelp.getBatchUpdateData(instockEditAttrUpdateDTO.getFieldEditedList());
                outstockUpdateDTO.setData(data);
                instockUpdateDTOS.add(outstockUpdateDTO);
            });
            List<InstockEntityExt> instockEntityList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            if (!instockUpdateDTOS.isEmpty()) {
                Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                param.put("corpid", instockEditAttrUpdateDTO.getCorpid());
                param.put("idIn", instockEditAttrUpdateDTO.getDataIdList());
                instockEntityList = instockModel.findEntitys(param);
                if (Objects.isNull(instockEntityList)){
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
                }
                InstockUpdateBatchDTO instockUpdateBatchDTO = new InstockUpdateBatchDTO();
                BeanUtil.copyProperties(instockEditAttrUpdateDTO, instockUpdateBatchDTO);
                instockUpdateBatchDTO.setOutstockList(instockUpdateDTOS);
                updateBatch(instockUpdateBatchDTO);
            }

            // 批量编辑日志
            List<String> updataItemList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            List<Long> dataIdList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (InstockEntityExt item : instockEntityList) {
                dataIdList.add(item.getId());
                String serialNo = item.getSerialNo();
                updataItemList.add(serialNo);
            }
            String updataItem = StringUtils.join(updataItemList, "，");
            String userId = instockEditAttrUpdateDTO.getUserId();
            String corpid = instockEditAttrUpdateDTO.getCorpid();
            String loginUserName = instockEditAttrUpdateDTO.getLoginUserName();
            // 标签特殊处理
            Integer fieldType = instockEditAttrUpdateDTO.getFieldType();
            Boolean isFieldDependence = instockEditAttrUpdateDTO.getIsFieldDependence();
            logHelp.analysisLabel(corpid, fieldType, isFieldDependence, instockEditAttrUpdateDTO.getLogFieldEditedList());

            String changedLogItemsStr = logHandleHelp.getChangedLogItemsStr(instockEditAttrUpdateDTO.getLogFieldEditedList());
            if(dataIdList.size() > 1 ){
                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_FORM_DATA_BATCH_ATTR), loginUserName, XbbRefTypeEnum.INSTOCK.getName(),
                        changedLogItemsStr, dataIdList.size());
                List<InfoArrPojo> infoArrPojoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                InfoArrPojo infoArrPojo = new InfoArrPojo();
                infoArrPojo.setTitle(XbbRefTypeEnum.INSTOCK.getName());
                infoArrPojo.setContent(updataItem);
                infoArrPojoList.add(infoArrPojo);
                mongoLogHelp.buildLog4InfoArr(infoArrPojoList, corpid, userId, loginUserName, OperateModuleTypeEnum.INSTOCK, OperateTypeEnum.EDIT,
                        "", "", memo, instockEditAttrUpdateDTO.getHttpHeader());
            } else if (Objects.equals(dataIdList.size(), 1)){
                String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_FORM_DATA_ATTR), loginUserName, XbbRefTypeEnum.INSTOCK.getName(), updataItem,
                        changedLogItemsStr);
                mongoLogHelp.buildLog(corpid, userId, loginUserName, OperateModuleTypeEnum.INSTOCK, OperateTypeEnum.EDIT,
                        dataIdList.get(0).toString(), updataItem, memo, instockEditAttrUpdateDTO.getHttpHeader());
            }
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("instockService.batchEditAttr 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }


    @Override
    public void formatLinkAddExplain(HandlerExplainInLinkItemDTO handlerExplainInLinkItemDTO) throws XbbException {
        PaasFormDataEntityExt paasFormDataEntityExt = handlerExplainInLinkItemDTO.getPaasFormDataEntityExt();
        JSONObject dataList = paasFormDataEntityExt.getData();
        PaasFormExplainEntity paasFormExplainEntity = handlerExplainInLinkItemDTO.getPaasFormExplainEntity();
        Integer businessType = paasFormExplainEntity.getBusinessType();
        String serialNo = paasFormDataEntityExt.getSerialNo();
        Long linkDataId = handlerExplainInLinkItemDTO.getLinkDataId();
        handlerExplainInLinkItemDTO.setBusinessType(businessType);
        String corpid = handlerExplainInLinkItemDTO.getCorpid();
        if (Objects.equals(handlerExplainInLinkItemDTO.getLinkBusinessType(),XbbRefTypeEnum.INVENTORY.getCode()) || Objects.equals(handlerExplainInLinkItemDTO.getLinkBusinessType(),XbbRefTypeEnum.TRANSFER.getCode())){
            // 调拨入库，盘盈入库有单据在审批中就不允许关联新建
            if (commonHelp.isOpenWorkFlow(corpid)) {
                BoolQueryBuilder boolQueryBuilder = boolQuery();
                boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
                boolQueryBuilder.filter(termQuery(ParameterConstant.DEL, DelEnum.NORMAL.getDel()));
                boolQueryBuilder.filter(termQuery(InstockEnum.getEsAttr4Keyword(InstockEnum.REF_ID), linkDataId));
                Integer type = InstockTypeEnum.getByBuisenssTypeInt(handlerExplainInLinkItemDTO.getLinkBusinessType());
                boolQueryBuilder.filter(termQuery(InstockEnum.getEsAttr4Keyword(InstockEnum.TYPE), type));

                boolQueryBuilder.filter(termsQuery("flowStatus", Arrays.asList(FlowStatusEnum.APPROVAL_PENDING.getType(), FlowStatusEnum.IN_APPROVAL.getType())));
                long count = paasEsModel.count(boolQueryBuilder, IndexTypeEnum.IDX_SAAS_INSTOCK);
                if (count > 0) {
                    throw new XbbException(InstockErrorCodeEnum.API_ERROR_210047);
                }
            } else {
                Map<String,Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                param.put(StringConstant.CORPID,corpid);
                param.put(StringConstant.DEL,DelEnum.NORMAL.getDel());
                param.put("firstRefId", linkDataId);
                param.put("formDataId", 0);
                param.put("businessType", XbbRefTypeEnum.OTHER_INSTOCK.getCode());
                param.put("flowStatusIn", Arrays.asList(FlowStatusEnum.APPROVAL_PENDING.getType(), FlowStatusEnum.IN_APPROVAL.getType()));
                param.put("sourceBusinessType", handlerExplainInLinkItemDTO.getLinkBusinessType());
                param.put("moduleType", 1);
                List<PaasProcessRelatedDataEntity> paasProcessRelatedDataList = paasProcessRelatedDataModel.findEntitys(param);
                if (!paasProcessRelatedDataList.isEmpty()) {
                    throw new XbbException(InstockErrorCodeEnum.API_ERROR_210047);
                }
            }
        }
        try {
            for (FieldAttrEntity fieldAttrEntity : handlerExplainInLinkItemDTO.getExplainList()) {
                if (Objects.equals(fieldAttrEntity.getIsRedundant(),1)){
                    continue;
                }
                if (Objects.equals(fieldAttrEntity.getAttr(), InstockEnum.REF_ID.getAttr())) {
                    RedundantTemplateTypeEnum redundantTemplateTypeEnum = RedundantTemplateTypeEnum.getByCode(handlerExplainInLinkItemDTO.getLinkBusinessType());
                    switch (redundantTemplateTypeEnum) {
                        case TRANSFER:
                            // 开启审批时关联新建走了addGet，导致可编辑
                            fieldAttrEntity.setEditable(0);
                            fieldAttrEntity.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(linkDataId, serialNo, paasFormDataEntityExt.getFormId()));
                            break;
                        case PURCHASE:
                        case INVENTORY:
                        case PRODUCTIONORDER:
                        case REFUND:
                            fieldAttrEntity.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(linkDataId, serialNo, paasFormDataEntityExt.getFormId()));
                            break;
                        default:
                            break;
                    }

                }else if (Objects.equals(fieldAttrEntity.getAttr(), InstockEnum.TYPE.getAttr())) {
                    String value = "";
                    if (Objects.equals(handlerExplainInLinkItemDTO.getAttr(), WorkFlowEnum.PRODUCTION_ORDER_PRODUCT_INSTOCK.getAttr())) {
                        value = String.valueOf(InstockTypeEnum.FINSHED_PRODUCT_INSTOCK.getCode());
                    } else if (Objects.equals(handlerExplainInLinkItemDTO.getAttr(), WorkFlowEnum.PRODUCTION_ORDER_MATERIEL_INSTOCK.getAttr())) {
                        value = String.valueOf(InstockTypeEnum.RETURNED_MATERIEL_INSTOCK.getCode());
                    } else {
                        value = InstockTypeEnum.getByBuisenssType(handlerExplainInLinkItemDTO.getLinkBusinessType());
                    }
                    for (ItemPoJo itemPoJo : fieldAttrEntity.getItems()) {
                        if (Objects.equals(value, itemPoJo.getValue())) {
                            itemPoJo.setChecked(true);
                        }else {
                            itemPoJo.setChecked(false);
                        }
                    }
                } else if (Objects.equals(fieldAttrEntity.getAttr(), InstockEnum.WAREHOUSE_ID.getAttr())) {
                    RedundantTemplateTypeEnum redundantTemplateTypeEnum = RedundantTemplateTypeEnum.getByCode(handlerExplainInLinkItemDTO.getLinkBusinessType());
                    switch (redundantTemplateTypeEnum) {
                        case INVENTORY:
                            fieldAttrEntity.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(FastJsonHelper.getJsonArrOrDefaultFromFormData(dataList, InventoryEnum.WAREHOUSE_ID.getAttr(), new JSONArray())));
                            fieldAttrEntity.setEditable(0);
                            break;
                        case TRANSFER:
                            fieldAttrEntity.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(FastJsonHelper.getJsonArrOrDefaultFromFormData(dataList, TransferEnum.INTO_WAREHOUSE_ID.getAttr(), new JSONArray())));
                            fieldAttrEntity.setEditable(0);
                            break;
                        case PRODUCTIONORDER:
                            if (Objects.equals(handlerExplainInLinkItemDTO.getAttr(), WorkFlowEnum.PRODUCTION_ORDER_MATERIEL_INSTOCK.getAttr())) {
                                // 退料入库仓库默认是生产单物料出库仓库
                                fieldAttrEntity.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(FastJsonHelper.getJsonArrOrDefaultFromFormData(dataList, ProductionOrderEnum.OUT_WAREHOUSE_ID.getAttr(), new JSONArray())));
                            } else {
                                fieldAttrEntity.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(FastJsonHelper.getJsonArrOrDefaultFromFormData(dataList, ProductionOrderEnum.INTO_WAREHOUSE_ID.getAttr(), new JSONArray())));
                            }
                            break;
                        default:
                            break;
                    }
                } else if (Objects.equals(fieldAttrEntity.getAttr(), InstockEnum.PRODUCT.getAttr())) {
                    explainHelp.formatSelectProductExplains(fieldAttrEntity, XbbRefTypeEnum.INSTOCK, handlerExplainInLinkItemDTO.getCorpid(), BasicConstant.ZERO, false);
                    BusinessProductListDTO businessProductListDTO = new BusinessProductListDTO();
                    BeanUtil.copyProperties(handlerExplainInLinkItemDTO, businessProductListDTO);
                    BeanUtil.copyProperties(paasFormExplainEntity, businessProductListDTO);
                    businessProductListDTO.setBusinessType(handlerExplainInLinkItemDTO.getLinkBusinessType());
                    businessProductListDTO.setSourceBusinessType(XbbRefTypeEnum.INSTOCK.getCode());
                    businessProductListDTO.setDataId(linkDataId);
                    businessProductListDTO.setFromInstock(BasicConstant.ONE);
                    RedundantTemplateTypeEnum redundantTemplateTypeEnum = RedundantTemplateTypeEnum.getByCode(handlerExplainInLinkItemDTO.getLinkBusinessType());
                    JSONArray productArray = new JSONArray();
                    switch (redundantTemplateTypeEnum) {
                        case PURCHASE:
                        case INVENTORY:
                        case TRANSFER:
                        case PRODUCTIONORDER:
                        case REFUND:
                            Integer type;
                            if (Objects.equals(handlerExplainInLinkItemDTO.getAttr(), WorkFlowEnum.PRODUCTION_ORDER_PRODUCT_INSTOCK.getAttr())) {
                                type = InstockTypeEnum.FINSHED_PRODUCT_INSTOCK.getCode();
                            } else if (Objects.equals(handlerExplainInLinkItemDTO.getAttr(), WorkFlowEnum.PRODUCTION_ORDER_MATERIEL_INSTOCK.getAttr())) {
                                type = InstockTypeEnum.RETURNED_MATERIEL_INSTOCK.getCode();
                                continue;
                            } else {
                                type = InstockTypeEnum.getByBuisenssTypeInt(handlerExplainInLinkItemDTO.getLinkBusinessType());
                            }
                            List<BusinessProductEntity> businessProductEntityList = formDataValidateProductHelp.searchUnInstockProduct(handlerExplainInLinkItemDTO.getCorpid(),handlerExplainInLinkItemDTO.getLinkDataId(),type, true);
                            List<OneKeyProduceProductPojo> productList = handlerExplainInLinkItemDTO.getProductList();
                            if (!productList.isEmpty()) {
                                Set<Long> oneKeyProduceProductSet = new HashSet<>();
                                productList.forEach(item -> oneKeyProduceProductSet.add(item.getId()));
                                businessProductEntityList.removeIf(businessProductEntity -> !oneKeyProduceProductSet.contains(businessProductEntity.getId()));
                            }
                            productArray = formatInstockLinkAdd(businessProductEntityList, fieldAttrEntity, type, handlerExplainInLinkItemDTO);
                            break;

                        default:
                            break;
                    }
                    // 校验关联产品是否开启序列号管理
                    productHelp.enableSrialCheck(handlerExplainInLinkItemDTO.getCorpid(), productArray, handlerExplainInLinkItemDTO);
                    String defaultType = "";
                    if (Objects.nonNull(fieldAttrEntity.getDefaultAttr()) && Objects.nonNull(fieldAttrEntity.getDefaultAttr().getDefaultType())) {
                        defaultType = fieldAttrEntity.getDefaultAttr().getDefaultType();
                    }
                    fieldAttrEntity.setDefaultAttr(saasUpdateHelp.setDefaultValue(productArray));
                    if (Objects.nonNull(defaultType) && !defaultType.isEmpty()) {
                        fieldAttrEntity.getDefaultAttr().setDefaultType(defaultType);
                    }
                }else if (Objects.equals(businessType,XbbRefTypeEnum.PURCHASE_INSTOCK.getCode())){
                    if (Objects.equals(fieldAttrEntity.getAttr(),PurchaseInstockEnum.SUPPLIER_ID.getAttr())){
                        fieldAttrEntity.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(FastJsonHelper.getJsonArrOrDefaultFromFormData(dataList, PurchaseEnum.SUPPLIER_ID.getAttr(), new JSONArray())));
                    }
                }else if (Objects.equals(businessType,XbbRefTypeEnum.REFUND_INSTOCK.getCode())){
                    if (Objects.equals(fieldAttrEntity.getAttr(),RefundInstockEnum.CUSTOMER_ID.getAttr())){
                        fieldAttrEntity.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(FastJsonHelper.getJsonArrOrDefaultFromFormData(dataList, RefundEnum.CUSTOMER_ID.getAttr(), new JSONArray())));
                    }
                } else if (Objects.equals(handlerExplainInLinkItemDTO.getLinkBusinessType(),XbbRefTypeEnum.TRANSFER.getCode())){
                    if (Objects.equals(fieldAttrEntity.getAttr(), InstockEnum.MEMO.getAttr())){
                        fieldAttrEntity.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(FastJsonHelper.getStringOrDefaultFromFormData(dataList, TransferEnum.MEMO.getAttr(), "")));
                    }
                }
//                // todo 关联新建需要带出来的东西最好都在这加
//                if (Objects.equals(businessType,XbbRefTypeEnum.PURCHASE_INSTOCK.getCode()) && Objects.equals(fieldAttrEntity.getAttr(), PurchaseInstockEnum.SUPPLIER_ID.getAttr())){
//                    RedundantTemplateTypeEnum redundantTemplateTypeEnum = RedundantTemplateTypeEnum.getByCode(handlerExplainInLinkItemDTO.getLinkBusinessType());
//                    switch (redundantTemplateTypeEnum) {
//                        case PURCHASE:
//                            fieldAttrEntity.setDefaultAttr(saasUpdateHelp.getDefaultAttrPojo(FastJsonHelper.getJsonArrOrDefaultFromFormData(dataList, PurchaseEnum.SUPPLIER_ID.getAttr(), new JSONArray())));
//                            break;
//                    }
//                }
            }

        } catch (XbbException e){
            throw e;
        }catch (Exception e) {
            LOG.error("instockService.formatLinkAddExplain 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    private JSONArray formatInstockLinkAdd(List<BusinessProductEntity> businessProductEntityList, FieldAttrEntity fieldAttrEntity, Integer type, HandlerExplainInLinkItemDTO handlerExplainInLinkItemDTO) throws XbbException {
        String corpid = handlerExplainInLinkItemDTO.getCorpid();
        Long formId = handlerExplainInLinkItemDTO.getFormId();
        Long sourceFormId = handlerExplainInLinkItemDTO.getSourceFormId();
        Long linkDataId = handlerExplainInLinkItemDTO.getLinkDataId();
        UserVO loginUser = handlerExplainInLinkItemDTO.getLoginUser();

        JSONArray productArray = new JSONArray();
        List<Long> dataIdList = new ArrayList<>();
        InstockTypeEnum instockTypeEnum = InstockTypeEnum.getByCode(type);
//        boolean isSource = Arrays.asList(InstockTypeEnum.PURCHASE_INSTOCK, InstockTypeEnum.RED_CONTRACT_INSTOCK, InstockTypeEnum.RETURNED_MATERIEL_INSTOCK).contains(instockTypeEnum);
        // 获取关联产品联动关系
        LinkProductRelyEntity linkProductRelyEntity;
        if (Objects.equals(handlerExplainInLinkItemDTO.getLinkBusinessType(), XbbRefTypeEnum.TRANSFER.getCode())) {
            linkProductRelyEntity = linkProductRelyModel.getByAttrAndFormIdAndSourceBusinessType(corpid, InstockEnum.PRODUCT.getAttr(), formId, XbbRefTypeEnum.OTHER_OUTSTOCK.getCode(), DelEnum.NORMAL.getDel());
        } else if (Objects.equals(handlerExplainInLinkItemDTO.getLinkBusinessType(), XbbRefTypeEnum.PRODUCTION_ORDER.getCode())) {
            PaasFormExplainEntity paasFormExplainEntity = handlerExplainInLinkItemDTO.getPaasFormExplainEntity();
            Integer businessType = paasFormExplainEntity.getBusinessType();
            if (Objects.equals(XbbRefTypeEnum.PRODUCTION_INSTOCK.getCode(), businessType)) {
                // 生产入库单联动生产单
                linkProductRelyEntity = linkProductRelyModel.getByAttrAndFormIdAndSourceBusinessType(corpid, InstockEnum.PRODUCT.getAttr(), formId, XbbRefTypeEnum.PRODUCTION_ORDER.getCode(), DelEnum.NORMAL.getDel());
            } else {
                // 生产退料单联动生产领料单
                linkProductRelyEntity = linkProductRelyModel.getByAttrAndFormIdAndSourceBusinessType(corpid, InstockEnum.PRODUCT.getAttr(), formId, XbbRefTypeEnum.PRODUCTION_MATERIEL_OUTSTOCK.getCode(), DelEnum.NORMAL.getDel());
            }
        } else {
            linkProductRelyEntity = linkProductRelyModel.getByAttrAndFormIdAndLinkFormId(corpid, InstockEnum.PRODUCT.getAttr(), formId, sourceFormId, DelEnum.NORMAL.getDel());
        }
        UserAndDepartmentGetDTO userAndDepartmentGetDTO = new UserAndDepartmentGetDTO();
        BeanUtil.copyProperties(handlerExplainInLinkItemDTO, userAndDepartmentGetDTO);
        UserAndDepartmentGetVO userAndDepartmentGetVO = userHelp.getUserDepartmentMap(userAndDepartmentGetDTO);
        Map<String, UserEntity> userMap = userAndDepartmentGetVO.getUserMap();
        Map<String, DepartmentEntity> departmentMap = userAndDepartmentGetVO.getDepartmentMap();
        Map<Long, String> unitMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (BusinessProductEntity entity : businessProductEntityList){
            JSONObject jsonObject = new JSONObject();
            jsonObject.put(InstockProductEnum.PRODUCT.getAttr(),entity.getProductId());
            jsonObject.put(MultiUnitConstant.RATE, entity.getRate());
            // 马雄2019/12/9 说要改掉
            jsonObject.put(InstockProductEnum.NUM.getAttr(),entity.getProductNum());
            jsonObject.put(InstockProductEnum.MEMO.getAttr(),entity.getMemo());
            jsonObject.put(InstockProductEnum.BATCH.getAttr(),entity.getBatch());
            jsonObject.put(InstockProductEnum.PRODUCE_DATE.getAttr(),entity.getProduceDate());
            if (Objects.nonNull(entity.getProduceDate()) && entity.getProduceDate() > 0L) {
                jsonObject.put(InstockProductEnum.GUARANTEE_PERIOD.getAttr(),entity.getGuaranteePeriod());
            }
            if (Objects.equals(InstockTypeEnum.RED_CONTRACT_INSTOCK.getCode(),type)){
                jsonObject.put(InstockProductEnum.COST.getAttr(),entity.getCost());
                jsonObject.put(SelectProductEnum.PRICE.getAttr(),entity.getPrice());
                if (Objects.nonNull(entity.getData())) {
                    jsonObject.put(SelectProductEnum.BATCH.getAttr(), entity.getData().getString(SelectProductEnum.BATCH.getAttr()));
                    if (Objects.nonNull(entity.getData().getLong(SelectProductEnum.PRODUCE_DATE.getAttr())) && entity.getData().getLong(SelectProductEnum.PRODUCE_DATE.getAttr()) > 0L) {
                        jsonObject.put(SelectProductEnum.GUARANTEE_PERIOD.getAttr(), entity.getData().getLong(SelectProductEnum.GUARANTEE_PERIOD.getAttr()));
                    }
                    jsonObject.put(SelectProductEnum.PRODUCE_DATE.getAttr(), entity.getData().getLong(SelectProductEnum.PRODUCE_DATE.getAttr()));
                }
            }else {
                jsonObject.put(InstockProductEnum.COST.getAttr(),entity.getPrice());
            }
            jsonObject.put(InstockProductEnum.MEMO.getAttr(),entity.getMemo());
            if (Objects.nonNull(entity.getRefProductId())) {
                jsonObject.put(BusinessConstant.REF_PRODUCT_ID,entity.getRefProductId());
                unitMap.put(entity.getRefProductId(), entity.getProductUnit());
            }
            jsonObject.put(InstockProductEnum.UNIT.getAttr(), formDataValidateProductHelp.formatUnit(corpid,entity.getProductUnit()));
            jsonObject.put(BusinessConstant.PRODUCT_SUB_ID,0);

            productArray.add(jsonObject);
            dataIdList.add(entity.getProductId());
        }
        JSONObject productData = new JSONObject();
        productData.put(InstockEnum.PRODUCT.getAttr(),productArray);
        //sku成本
        Map<Object, Double> costMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        //sku库存
        Map<Object, Double> stockMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Object, Long> refundWarehouseMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        //调拨、盘点要拿产品成本
        JSONArray warehouseObj = new JSONArray();
        if (Objects.equals(instockTypeEnum.getCode(),InstockTypeEnum.INVENTORY_INSTOCK.getCode()) || Objects.equals(instockTypeEnum.getCode(),InstockTypeEnum.FINSHED_PRODUCT_INSTOCK.getCode())) {
            warehouseObj = formDataValidateProductHelp.getWarehouseObj(corpid,linkDataId,instockTypeEnum.getBusinessType(),true);
            Long warehouseId = warehouseObj.getJSONObject(0).getLong("id");
//            formDataValidateProductHelp.getSkuWarehouseCost(dataIdList,warehouseId,corpid,costMap,stockMap);
//            formDataValidateProductHelp.getSkuWarehouseOrBatchCost(productArray, warehouseId, corpid, costMap, stockMap);
            productValidateHelp.getInventorySkuWarehouseOrBatchCost(productArray, warehouseId, corpid, costMap, stockMap);
        } else if (Objects.equals(instockTypeEnum.getCode(),InstockTypeEnum.RETURNED_MATERIEL_INSTOCK.getCode())) {
            warehouseObj = formDataValidateProductHelp.getWarehouseObj(corpid,linkDataId,instockTypeEnum.getBusinessType(),false);
            Long warehouseId = warehouseObj.getJSONObject(0).getLong("id");
            formDataValidateProductHelp.getSkuWarehouseOrBatchCost(productArray, warehouseId, corpid, costMap, stockMap);
        } else if (Objects.equals(instockTypeEnum.getCode(),InstockTypeEnum.TRANSFER_INSTOCK.getCode())) {
            // 调拨入库的关联产品取调拨单入库仓库的产品
            warehouseObj = formDataValidateProductHelp.getWarehouseObj(corpid,linkDataId,instockTypeEnum.getBusinessType(),true);
            Long warehouseId = warehouseObj.getJSONObject(0).getLong("id");
            formDataValidateProductHelp.getSkuWarehouseOrBatchCost(productArray, warehouseId, corpid, costMap, stockMap);
            Integer accuracy = costMap.get("costField").intValue();
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("corpid", corpid);
            param.put("del", DelEnum.NORMAL.getDel());
            param.put("type", OutstockTypeEnum.TRANSFER_OUTSTOCK.getCode());
            param.put("refId", linkDataId);
            List<BusinessProductEntity> transferOutstockProduct = outstockProductModel.findProductNum(param);
            for (BusinessProductEntity businessProductEntity : transferOutstockProduct) {
                if (Objects.nonNull(businessProductEntity.getPriceData()) && !businessProductEntity.getPriceData().isEmpty()) {
                    businessProductEntity.setCost(businessProductEntity.getPriceData().getDouble(SelectProductEnum.COST.getAttr()));
                }
                costMap.put(businessProductEntity.getId(), attrDecimalPrecisionHelper.setPrecision(businessProductEntity.getCost(), accuracy));
            }
        } else if (Objects.equals(instockTypeEnum.getCode(), InstockTypeEnum.RED_CONTRACT_INSTOCK.getCode())) {
            // 退货退款入库取销售出库成本
            PaasFormDataEntityExt paasFormDataEntityExt = refundModel.getByKey(linkDataId, corpid);
            Long contractId = paasFormDataEntityExt.getData().getLong(RefundEnum.CONTRACT_ID.getAttr());
            Long redContractId = paasFormDataEntityExt.getData().getLong(RefundEnum.RED_CONTRACT_ID.getAttr());

            Map<String,Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("corpid",corpid);
            param.put("del",0);
            param.put("contractId", redContractId);
            List<ContractProductEntity> refundProductEntityList = contractProductModel.findEntitys(param);
            boolean needMerge = true;
            for (ContractProductEntity contractProductEntity : refundProductEntityList) {
                if (Objects.nonNull(contractProductEntity.getRefProductId()) && !Objects.equals(contractProductEntity.getRefProductId(), 0)) {
                    needMerge = false;
                    break;
                }
            }
            param.clear();
            param.put("corpid", corpid);
            param.put("del", 0);
            param.put("refId", contractId);
            param.put("type", OutstockTypeEnum.CONTRACT_OUTSTOCK.getCode());
            List<OutstockProductEntity> outstockProductEntityList = outstockProductModel.findEntitys(param);
            Map<Long, Double> totalCostMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Map<Long, Double> totalNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            if (needMerge) {
                for (OutstockProductEntity outstockProductEntity : outstockProductEntityList) {
                    Long productId = outstockProductEntity.getProductId();
                    Double extraCost = Arith.mul(outstockProductEntity.getCost(), outstockProductEntity.getProductNum());
                    if (totalCostMap.containsKey(productId)) {
                        Double totalCost = totalCostMap.get(productId);
                        totalCostMap.put(productId, Arith.add(totalCost, extraCost));
                    } else {
                        totalCostMap.put(productId, extraCost);
                    }
                    if (totalNumMap.containsKey(productId)) {
                        Double totalNum = totalNumMap.get(productId);
                        totalNumMap.put(productId, Arith.add(totalNum, outstockProductEntity.getProductNum()));
                    } else {
                        totalNumMap.put(productId, outstockProductEntity.getProductNum());
                    }
                }
            }

            for (Long productId : dataIdList) {
                if (needMerge) {
                    if (totalCostMap.containsKey(productId) && totalNumMap.containsKey(productId) && !Objects.equals(totalNumMap.get(productId),0D)) {
                        costMap.put(productId, Arith.div(totalCostMap.get(productId), totalNumMap.get(productId)));
                    }
                } else {
                    for (ContractProductEntity refundProduct : refundProductEntityList) {
                        if (Objects.equals(productId, refundProduct.getProductId())) {
                            Long refProductId = refundProduct.getRefProductId();
                            for (OutstockProductEntity outstockProductEntity : outstockProductEntityList) {
                                if (Objects.equals(outstockProductEntity.getId(), refProductId)) {
                                    if (Objects.nonNull(outstockProductEntity.getBusinessUnit()) && Objects.nonNull(outstockProductEntity.getPriceData()) && Objects.equals(refundProduct.getBusinessUnit(), outstockProductEntity.getBusinessUnit()) && Objects.equals(Objects.toString(refundProduct.getBusinessUnit(),""), unitMap.get(refundProduct.getId()))) {
                                        outstockProductEntity.setCost(outstockProductEntity.getPriceData().getDouble(SelectProductEnum.COST.getAttr()));
                                    }
                                    costMap.put(productId + "_" + refundProduct.getId(), outstockProductEntity.getCost());
                                    refundWarehouseMap.put(productId + "_" + refundProduct.getId(), outstockProductEntity.getWarehouseId());
                                    break;
                                }
                            }
                        }
                    }
                }
            }
            for (int i = 0; i < productArray.size(); i++) {
                JSONObject jsonObject = productArray.getJSONObject(i);
                Long productId = FastJsonHelper.getLongOrDefaultFromFormData(jsonObject, SelectProductEnum.PRODUCT.getAttr(), 0L);
                if (Objects.nonNull(jsonObject.get(BusinessConstant.REF_PRODUCT_ID))) {
                    Long warehouseId = refundWarehouseMap.getOrDefault(productId + "_" + jsonObject.get(BusinessConstant.REF_PRODUCT_ID), 0L);
                    jsonObject.put(SelectProductEnum.WAREHOUSE.getAttr(), warehouseId);
                }
            }
            formDataValidateProductHelp.getSkuWarehouseOrBatchCost(productArray, corpid, costMap, stockMap);
        }
        //分仓库存和成本
        Map<Long,Map<String,JSONObject>> productMap = formDataValidateProductHelp.getWarehouseMap(dataIdList,corpid);
        JSONArray newProductArray = formDataValidateProductHelp.otherProductToAnother(productData,fieldAttrEntity,InstockEnum.PRODUCT.getAttr(),InstockEnum.PRODUCT.getAttr(),corpid, loginUser, handlerExplainInLinkItemDTO.getBusinessType(), handlerExplainInLinkItemDTO.getLinkBusinessType());
        DefaultAttrPoJo defaultAttr = fieldAttrEntity.getDefaultAttr();
        String defaultType = defaultAttr.getDefaultType();
        // 源单解释
        Map<String, FieldAttrEntity> sourceExplainMap = null;
        // 当前表单解释
        Map<String, FieldAttrEntity> thisExplainMap = null;
        // 当前表单某个关联产品解释
        Map<String, FieldAttrEntity> subThisExplainMap = null;
        // 源单某个关联产品解释
        Map<String, FieldAttrEntity> subSourceExplainMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        // 当前表单某个关联产品子字段与源单某个关联产品对应关系
        Map<String, String> thisToTarget = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (Objects.nonNull(defaultType) && Objects.equals(defaultType, DefaultTypeEnum.PRODUCT_DATA_RELY.getAlias()) && Objects.nonNull(linkProductRelyEntity)) {
            // 源数据表单
            PaasFormExplainEntity paasFormExplainEntity = proFormHelp.getExplainEntity(corpid, linkProductRelyEntity.getSourceFormId(), linkProductRelyEntity.getSourceBusinessType());
            List<FieldAttrEntity> explainList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
            sourceExplainMap = ExplainUtil.getExplainMapByList(explainList, null);
            // 当前表单解释
            PaasFormExplainEntity displayFormExplain = proFormHelp.getExplainEntity(corpid, linkProductRelyEntity.getFormId(), linkProductRelyEntity.getBusinessType());
            thisExplainMap = ExplainUtil.getExplainMap(displayFormExplain.getExplains(), null);
            subThisExplainMap = businessProductService.getProductRelyMap(InstockEnum.PRODUCT.getAttr(), linkProductRelyEntity, sourceExplainMap, thisExplainMap, subSourceExplainMap, thisToTarget);

            for (BusinessProductEntity entity : businessProductEntityList){
                JSONObject entityData = entity.getData();
                if (Objects.nonNull(entityData) && !thisToTarget.isEmpty()) {
                    ParseSingleRowDataDTO parseSingleRowDataDTO = new ParseSingleRowDataDTO();
                    parseSingleRowDataDTO.setDataJsonObject(entityData);
                    parseSingleRowDataDTO.setDepartmentMap(departmentMap);
                    parseSingleRowDataDTO.setUserMap(userMap);
                    parseSingleRowDataDTO.setExplainMap(subSourceExplainMap);
                    ParseSingleRowDataVO parseSingleRowDataVO = formDataUpdateGetAnalysisDataHelp.parseSingleRowData(parseSingleRowDataDTO);
                    if (Objects.isNull(parseSingleRowDataVO)) {
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PARSE_SINGLE_ROW_DATA_FAILED);
                    }
                    JSONObject result = parseSingleRowDataVO.getResult();
                    JSONObject thisData = businessProductService.formatThisFormData(subThisExplainMap, thisToTarget, result);
                    for (int i = 0; i < newProductArray.size(); i++) {
                        JSONObject jsonObject = newProductArray.getJSONObject(i);
                        if (Objects.equals(jsonObject.getLongValue(BusinessConstant.REF_PRODUCT_ID), entity.getRefProductId())) {
                            jsonObject.putAll(thisData);
                            break;
                        }
                    }
                }
            }
        }
        for (int i = 0;i < newProductArray.size();i++){
            JSONObject jsonObject = newProductArray.getJSONObject(i);
            JSONObject product = jsonObject.getJSONObject(SelectProductEnum.PRODUCT.getAttr());
            double rate = Objects.nonNull(jsonObject.getDouble(MultiUnitConstant.RATE)) ? jsonObject.getDouble(MultiUnitConstant.RATE) : 1D;
            JSONObject sellingMap = Objects.nonNull(jsonObject.getJSONObject(ProductConstant.SELLING_PRICE_MAP)) ? jsonObject.getJSONObject(ProductConstant.SELLING_PRICE_MAP) : new JSONObject();
            sellingMap.put(SelectProductEnum.UNIT.getAttr(), jsonObject.get(SelectProductEnum.UNIT.getAttr()));
            Long productId = product.getLong("dataId");
            JSONObject data = product.getJSONObject("data");
            if (Objects.isNull(data)) {
                data = new JSONObject();
            }
            JSONObject sourceData = new JSONObject();
            Map<String, JSONObject> warehouseMap = productMap.getOrDefault(productId, new HashMap<>());
            sourceData.put("warehouse", warehouseMap);
            product.put("sourceData",sourceData);

            String batch = jsonObject.getString(SelectProductEnum.BATCH.getAttr());
            jsonObject.put(InstockProductEnum.WAREHOUSE.getAttr(), warehouseObj);
            Long warehouseId = 0L;
            if (!warehouseObj.isEmpty()) {
                warehouseId = warehouseObj.getJSONObject(0).getLong("id");
            }else if (Objects.equals(instockTypeEnum.getCode(), InstockTypeEnum.RED_CONTRACT_INSTOCK.getCode())){
                warehouseId = refundWarehouseMap.getOrDefault(productId + "_" + jsonObject.get(BusinessConstant.REF_PRODUCT_ID), 0L);
            }
            //分为取批次成本丶库存和分仓成本丶库存
            Object key;
            if (StringUtil.isNotEmpty(batch)) {
                key = formDataValidateProductHelp.getBatchKey(productId, warehouseId, batch, jsonObject.getLong(SelectProductEnum.PRODUCE_DATE.getAttr()), FastJsonHelper.getLongOrDefaultFromFormData(jsonObject, SelectProductEnum.GUARANTEE_PERIOD.getAttr(), 0L) * TimeConstant.SECONDS_PER_DAY);
            }else {
                key = productId + "_" + warehouseId;
            }

            if (Objects.equals(instockTypeEnum.getCode(),InstockTypeEnum.INVENTORY_INSTOCK.getCode()) || Objects.equals(instockTypeEnum.getCode(),InstockTypeEnum.FINSHED_PRODUCT_INSTOCK.getCode()) || Objects.equals(instockTypeEnum.getCode(),InstockTypeEnum.RETURNED_MATERIEL_INSTOCK.getCode())) {
                jsonObject.put(InstockProductEnum.STOCK.getAttr(), stockMap.getOrDefault(key, 0D));
                jsonObject.put(InstockProductEnum.COST.getAttr(), Arith.mul(rate, costMap.getOrDefault(key, 0D)));
                sellingMap.put(SelectProductEnum.COST.getAttr(), jsonObject.get(SelectProductEnum.COST.getAttr()));
            }else if (Objects.equals(instockTypeEnum.getCode(),InstockTypeEnum.TRANSFER_INSTOCK.getCode())){
                //调拨入库需要取调拨出库的陈本
                jsonObject.put(InstockProductEnum.STOCK.getAttr(), stockMap.getOrDefault(key, 0D));
                jsonObject.put(InstockProductEnum.COST.getAttr(), costMap.getOrDefault(FastJsonHelper.getLongOrDefaultFromFormData(jsonObject, BusinessConstant.REF_PRODUCT_ID, 0L), 0D));
                sellingMap.put(SelectProductEnum.COST.getAttr(), jsonObject.get(SelectProductEnum.COST.getAttr()));
            }
            if (Objects.equals(instockTypeEnum.getCode(), InstockTypeEnum.PURCHASE_INSTOCK.getCode())) {
                data.put(SelectProductEnum.SOURCE_PRICE.getAttr(),jsonObject.get(SelectProductEnum.COST.getAttr()));
            }else if (Objects.equals(instockTypeEnum.getCode(), InstockTypeEnum.RED_CONTRACT_INSTOCK.getCode())) {
                jsonObject.put(InstockProductEnum.COST.getAttr(), costMap.getOrDefault(productId, 0D));
                if (Objects.nonNull(jsonObject.get(BusinessConstant.REF_PRODUCT_ID))) {
                    jsonObject.put(InstockProductEnum.COST.getAttr(), costMap.getOrDefault(productId + "_" + jsonObject.get(BusinessConstant.REF_PRODUCT_ID), 0D));
                    String refundWarehouseId = refundWarehouseMap.getOrDefault(productId + "_" + jsonObject.get(BusinessConstant.REF_PRODUCT_ID), 0L).toString();
                    JSONArray warehouseArray = new JSONArray();
                    JSONObject refundWarehouseObj = new JSONObject();
                    refundWarehouseObj.put("id", refundWarehouseId);
                    refundWarehouseObj.put("name", warehouseMap.getOrDefault(refundWarehouseId, new JSONObject()).getString(ProductEnum.WAREHOUSE.getSaasAttr()));
                    warehouseArray.add(refundWarehouseObj);
                    jsonObject.put(InstockProductEnum.WAREHOUSE.getAttr(), warehouseArray);
                    jsonObject.put(InstockProductEnum.STOCK.getAttr(), stockMap.getOrDefault(key, 0D));
                }
                sellingMap.put(SelectProductEnum.COST.getAttr(), jsonObject.get(SelectProductEnum.COST.getAttr()));
                jsonObject.put(RefundInstockProductEnum.PRICE.getAttr(), getDoubleOrDefaultFromFormData(data, SelectProductEnum.PRICE.getAttr(), 0D));
                sellingMap.put(RefundInstockProductEnum.PRICE.getAttr(), jsonObject.get(RefundInstockProductEnum.PRICE.getAttr()));
                jsonObject.put(RefundInstockProductEnum.SUBTOTAL.getAttr(), jsonObject.getDouble(SelectProductEnum.PRICE.getAttr()) * jsonObject.getDouble(InstockProductEnum.NUM.getAttr()));
                data.put(SelectProductEnum.SOURCE_PRICE.getAttr(),data.get(SelectProductEnum.PRICE.getAttr()));
            }
            jsonObject.put(InstockProductEnum.TOTAL_COST.getAttr(),jsonObject.getDouble(InstockProductEnum.COST.getAttr()) * jsonObject.getDouble(InstockProductEnum.NUM.getAttr()));
            if (Objects.nonNull(jsonObject.get(SelectProductEnum.PRODUCE_DATE.getAttr())) && Objects.nonNull(jsonObject.get(SelectProductEnum.GUARANTEE_PERIOD.getAttr()))) {
                jsonObject.put(InstockProductEnum.EXPIRE_DATE.getAttr(), jsonObject.getLong(SelectProductEnum.PRODUCE_DATE.getAttr()) + (TimeConstant.SECONDS_PER_DAY * jsonObject.getLong(SelectProductEnum.GUARANTEE_PERIOD.getAttr())));
            }
        }
        return newProductArray;
    }

    @Override
    public void formatGetExplain(FormatExplainDTO formatExplainDTO) throws XbbException {
        try {
            JSONObject dataObj = formatExplainDTO.getResult();
            if (Objects.isNull(dataObj)) {
                return;
            }
        } catch (Exception e) {
            LOG.error("instockService.formatGetExplain 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    @Override
    public FormDataAddDTO formatExcelValue(ImportFormDataDTO importFormDataDTO, List<CellTitlePojo> titlePojoList, RowGroupPojo rowGroupPojo, List<FieldAttrEntityForImport> fieldAttrList) throws XbbException {
        FormDataAddDTO formDataAddDTO = new FormDataAddDTO();
        BeanUtil.copyProperties(importFormDataDTO, formDataAddDTO);
        String corpid = importFormDataDTO.getCorpid();
        Integer businessType = importFormDataDTO.getBusinessType();
        // data 数据
        JSONObject dataJson = new JSONObject();

        List<List<CellValuePojo>> rowValueList = rowGroupPojo.getRowValueList();
        // 分组的第一条数据作为给实体对象赋值的数据
        List<CellValuePojo> cellValueList = rowValueList.get(0);
        // 上游产品信息
        FieldAttrEntityForImport sheetNoAttrEntity = null;
        FieldAttrEntityForImport linkSupplierAttr = null;
        for (FieldAttrEntityForImport item : fieldAttrList) {
            if (Objects.equals(item.getAttr(), InstockEnum.SHEET_NO.getAttr())) {
                sheetNoAttrEntity = item;
            } else if (Objects.equals(item.getAttr(), PurchaseInstockEnum.SUPPLIER_ID.getAttr())) {
                linkSupplierAttr = item;
            }
        }
        // 遍历数据
        String refId = null;
        Long linkSupplierId = 0L;
        if (Objects.nonNull(linkSupplierAttr)) {
            Integer columnIndex = importHelper.getColumnIndexByTitle(titlePojoList, linkSupplierAttr.getAttrName(), null);
            Object cellValue = importHelper.getValueByColumnIndex(cellValueList, columnIndex);
            linkSupplierId = importHelper.formatSuppplier2SupplierId(cellValue.toString(), dataJson, linkSupplierAttr);
        }

        for (FieldAttrEntityForImport fieldAttrEntityForImport : fieldAttrList) {
            String attr = fieldAttrEntityForImport.getAttr();
            Integer fieldType = fieldAttrEntityForImport.getFieldType();
            String attrName = fieldAttrEntityForImport.getAttrName();
            Integer columnIndex = importHelper.getColumnIndexByTitle(titlePojoList, attrName, null);
            Object cellValue = importHelper.getValueByColumnIndex(cellValueList, columnIndex);

            if (Objects.equals(attr, PurchaseInstockEnum.SUPPLIER_ID.getAttr())) {

            } else if (Objects.equals(attr, InstockEnum.PRODUCT.getAttr())) {
                importHelper.formatCommonProduct(titlePojoList, dataJson, rowValueList, fieldAttrEntityForImport, businessType, corpid);
            } else if (Objects.equals(fieldType, FieldTypeEnum.SUB_FORM.getType())) {
                importHelper.formatSubFormValue4Import(rowValueList, titlePojoList, importFormDataDTO, fieldAttrEntityForImport, dataJson);
            } else if (Objects.equals(attr, InstockEnum.REF_ID.getAttr())) {
                if (Objects.equals(businessType, XbbRefTypeEnum.PURCHASE_INSTOCK.getCode())) {
                    refId = importHelper.formatRelyBusiness(linkSupplierId, dataJson, fieldAttrEntityForImport, cellValue, PurchaseEnum.SUPPLIER_ID.getAttr()).toString();
                }
            } else if (Objects.equals(attr, InstockEnum.MANAGER_ID.getAttr())) {
                importHelper.formatOwnId4Import(formDataAddDTO, fieldAttrEntityForImport, cellValue);
            } else if (Objects.equals(attr, InstockEnum.WAREHOUSE_ID.getAttr())) {
                importHelper.formatWareHouse4Import(dataJson, fieldAttrEntityForImport, attr, cellValue);
            } else if (Objects.equals(fieldType, FieldTypeEnum.SERIALNO.getType())) {
                if (Objects.isNull(cellValue) || StringUtil.isEmpty(cellValue.toString())) {
                    throw new XbbException(BuinessDefaultErrorCodeEnum.API_ERROR_200022);
                }
                formDataAddDTO.setSerialNo(cellValue.toString());
            } else if (Objects.equals(attr, InstockEnum.TYPE.getAttr()) && Objects.equals(businessType, XbbRefTypeEnum.OTHER_INSTOCK.getCode())){
                if (!Objects.equals(cellValue.toString(), InstockTypeEnum.OTHER_INSTOCK.getName())) {
                    throw new XbbException(ImportErrorCodeEnum.API_ERROR_235038, String.format(ImportErrorCodeEnum.API_ERROR_235038.getMsg(), InstockTypeEnum.OTHER_INSTOCK.getName()));
                }
                dataJson.put(attr, String.valueOf(InstockTypeEnum.OTHER_INSTOCK.getCode()));
            } else if (Objects.equals(attr, InstockEnum.TIME.getAttr())) {
                Long time = DateTimeUtil.getExcelTime(cellValue.toString());
                if (time == 0L) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028, ErrorMessageConstant.FORMAT_INVALID, fieldAttrEntityForImport.getAttrName());
                }
                SettleAccountsEntity accountsEntity = settleAccountsModel.getLastSettleAccounts(corpid);
                //校验日期是否受结账限制
                if (Objects.nonNull(accountsEntity) && Objects.nonNull(accountsEntity.getCheckOutTime())) {
                    if (time <= DateTimeUtil.getTodayEndInt(accountsEntity.getCheckOutTime())) {
                        throw new XbbException(OutstockErrorCodeEnum.API_ERROR_212035);
                    }
                }
                dataJson.put(attr, time);
            } else {
                if (Objects.isNull(cellValue) || StringUtil.isEmpty(cellValue.toString())) {
                    continue;
                }
                if (ImportHelper.commonHandleFieldType.contains(fieldAttrEntityForImport.getFieldType())) {
                    importHelper.formatCommonField(dataJson, fieldAttrEntityForImport, cellValue);
                } else if (Objects.equals(fieldType, FieldTypeEnum.LINK_DATA.getType())) {
                    importHelper.formatLinkData(cellValue, fieldAttrEntityForImport, dataJson);
                } else if (Objects.equals(fieldType, FieldTypeEnum.LINK_DATA_MULTI.getType())) {
                    importHelper.formatLinkDataMulti(cellValue, importFormDataDTO, fieldAttrEntityForImport, dataJson);
                } else {
                    dataJson.put(attr, cellValue);
                }
            }
        }
        if (Objects.equals(businessType, XbbRefTypeEnum.PURCHASE_INSTOCK.getCode())) {
            if (Objects.nonNull(sheetNoAttrEntity) && Objects.nonNull(sheetNoAttrEntity.getLinkBusinessMap()) && sheetNoAttrEntity.getLinkBusinessMap().containsKey(refId)) {
                List<PurchaseProductEntity> productEntityList = (List<PurchaseProductEntity>) sheetNoAttrEntity.getLinkBusinessMap().get(refId);
                Map<Long, PurchaseProductEntity> refProduct = new HashMap<>(productEntityList.size());
                for (PurchaseProductEntity item : productEntityList) {
                    if (refProduct.containsKey(item.getProductId())) {
                        throw new XbbException(ImportErrorCodeEnum.API_ERROR_235036);
                    } else {
                        refProduct.put(item.getProductId(), item);
                    }
                }
                JSONArray productJsonArray = dataJson.getJSONArray(PurchaseInstockEnum.PRODUCT.getAttr());
                Set<Long> repeatLineList = new HashSet<>();
                for (int i = 0; i < productJsonArray.size(); i++) {
                    JSONObject jsonObject = productJsonArray.getJSONObject(i);
                    Long productId = jsonObject.getJSONObject(SelectProductEnum.PRODUCT.getAttr()).getLong(StringConstant.DATA_ID);
                    if (refProduct.containsKey(productId)) {
                        Long refProductId = refProduct.get(productId).getId();
                        if (repeatLineList.contains(refProductId)) {
                            throw new XbbException(ImportErrorCodeEnum.API_ERROR_235041);
                        }
                        Integer enableMultiUnit = jsonObject.getInteger(ProductEnum.ENABLE_MULTI_UNIT.getSaasAttr());
                        boolean isSwitchUnit = false;
                        if (Objects.equals(BasicConstant.ONE, enableMultiUnit)){
                            JSONObject unitObject = (JSONObject) jsonObject.get(ProductEnum.UNIT.getAttr());
                            PurchaseProductEntity purchaseProductEntity = refProduct.get(productId);
                            List<UnitItemPoJo> transformUnitRate = (List<UnitItemPoJo>)jsonObject.get(ProductConstant.TRANSFORM_UNIT_RATE);
                            Long baseValue = null;
                            for (UnitItemPoJo unitItemPoJo : transformUnitRate) {
                                if (Objects.equals(unitItemPoJo.getIsBase(), 1)) {
                                    baseValue = unitItemPoJo.getValue();
                                    break;
                                }
                            }
                            Set<Long> unitIdSet = new HashSet<>();
                            if (!Objects.equals(unitObject.getLong(BasicConstant.VALUE) , purchaseProductEntity.getBusinessUnit() == null ? purchaseProductEntity.getProductUnit() : purchaseProductEntity.getBusinessUnit())){
                                isSwitchUnit =true;
                            }
                            //没有groupId是上游单据中的单位为基本单位
                            unitIdSet.add(purchaseProductEntity.getBusinessUnit());
                            unitIdSet.add(baseValue);
                            if (!unitIdSet.contains(unitObject.getLong(BasicConstant.VALUE))){
                                throw new XbbException(ImportErrorCodeEnum.API_ERROR_235049, String.format(ImportErrorCodeEnum.API_ERROR_235049.getMsg(), purchaseProductEntity.getProductName() + "(" + purchaseProductEntity.getProductSpecification()+ ")"));
                            }
                        }
                        repeatLineList.add(refProductId);
                        jsonObject.put(BusinessConstant.REF_PRODUCT_ID, refProductId);
                        Double cost = refProduct.get(productId).getProductPrice();
                        if (!isSwitchUnit){
                            if(Objects.nonNull(refProduct.get(productId).getPriceData())){
                                cost = refProduct.get(productId).getPriceData().get(SelectProductEnum.PRICE.getAttr()) == null ? refProduct.get(productId).getProductPrice():refProduct.get(productId).getPriceData().getDouble(SelectProductEnum.PRICE.getAttr());
                            }
                        }
                        jsonObject.put(SelectProductEnum.COST.getAttr(), cost);
                        jsonObject.put(SelectProductEnum.TOTAL_COST.getAttr(), Arith.mul(cost, jsonObject.getDouble(SelectProductEnum.NUM.getAttr())));
                    } else {
                        throw new XbbException(ImportErrorCodeEnum.API_ERROR_235031);
                    }
                }
            } else {
                throw new XbbException(ImportErrorCodeEnum.API_ERROR_235010);
            }
        }
        formDataAddDTO.setDataList(dataJson);
        return formDataAddDTO;
    }

    @Override
    public void formatExportValue(List<PaasFormDataEntityExt> paasFormDataESList, FormDataListDTO formDataListDTO, List<FieldAttrEntityForImport> fieldAttrList) throws XbbException {
        // 所有产品map
        List<Long> idList = new ArrayList<>();
        paasFormDataESList.forEach(item -> idList.add(item.getDataId()));
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        params.put(ParameterConstant.CORPID, formDataListDTO.getCorpid());
        params.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        List<ProductEntityExt> productList = productModel.findEntitys(params);
        Map<Long, ProductEntityExt> productMap = new HashMap<>();
        productList.forEach(item -> productMap.put(item.getId(), item));
        // 入库关联产品map
        params.put("instockIdIn", idList);
        params.put("orderByStr","sort");
        List<InstockProductEntity> instockProductList = instockProductModel.findEntitys(params);
        Map<Long, List<InstockProductEntity>> instockProductMap = new HashMap<>();
        instockProductList.forEach(item -> {
            Long refId = item.getIntoWarehouseId();
            if (instockProductMap.containsKey(refId)) {
                instockProductMap.get(refId).add(item);
            } else {
                List<InstockProductEntity> productEntityList = new ArrayList<>();
                productEntityList.add(item);
                instockProductMap.put(refId, productEntityList);
            }
        });

        // 所有仓库map
        params.remove("instockIdIn");
        params.remove("orderByStr");
        List<WarehouseEntityExt> warehouseList = warehouseModel.findEntitys(params);
        Map<Long, WarehouseEntityExt> warehouseMap = new HashMap<>();
        warehouseList.forEach(item -> warehouseMap.put(item.getId(), item));

        Set<Long> warehouseIdList = new HashSet<>();
        Set<Long> batchProductIdList = new HashSet<>();
        Set<Long> batchWarehouseIdList = new HashSet<>();
        Set<String> batchList = new HashSet<>();
        Set<Long> productIdList = new HashSet<>();
        for (InstockProductEntity instockProductEntity : instockProductList) {
            Long productId = instockProductEntity.getProductId();
            Long warehouseId = instockProductEntity.getWarehouseId();
            String batch = instockProductEntity.getBatch();
            if (StringUtil.isNotEmpty(batch)) {
                batchProductIdList.add(productId);
                batchWarehouseIdList.add(warehouseId);
                batchList.add(batch);
            }
            warehouseIdList.add(warehouseId);
            productIdList.add(productId);
        }


        // 产品，库存产品
        FieldAttrEntityForImport productFieldAttr = new FieldAttrEntityForImport();
        for (FieldAttrEntityForImport item : fieldAttrList) {
            if (Objects.equals(item.getAttr(), InstockEnum.PRODUCT.getAttr())) {
                productFieldAttr = item;
            }
        }

        // 精度
        SubFormPoJo subFormPoJo = productFieldAttr.getSubForm();
        List<? extends FieldAttrEntity> subFieldAttrList = new ArrayList<>();
        if (Objects.nonNull(subFormPoJo)){
            subFieldAttrList = subFormPoJo.getItems();
        }
        int accuracy = 2;
        boolean costVisible = false;
        boolean costOpen = false;
        FieldAttrEntity costFieldAttrEntity = new FieldAttrEntity();
        for (FieldAttrEntity item : subFieldAttrList) {
            if (Objects.equals(item.getAttr(), SelectProductEnum.COST.getAttr())) {
                accuracy = item.getAccuracy() == null ? 2 : item.getAccuracy();
                costVisible = Objects.equals(item.getVisible(), 1);
                costOpen = Objects.equals(item.getIsOpen(), 1);
                costFieldAttrEntity = item;
                break;
            }
        }
        HandlerExplainDTO handlerExplainDTO = new HandlerExplainDTO();
        handlerExplainDTO.setLoginUser(formDataListDTO.getLoginUser());
        handlerExplainDTO.setUserId(formDataListDTO.getUserId());

        Map<String, MultiUnitItemPoJo> groupBaseUnitStringMap = relativeProductHelp.getGroupBaseUnitStringMap(formDataListDTO.getCorpid());
        // 暂时只处理产品
        for (PaasFormDataEntityExt paasFormDataEntityExt : paasFormDataESList) {
            JSONObject formDataObj = paasFormDataEntityExt.getData();
            String productAttr = productFieldAttr.getAttr();
            Long dataId = paasFormDataEntityExt.getDataId();
            handlerExplainDTO.setCreatorId(paasFormDataEntityExt.getCreatorId());
            handlerExplainDTO.setOwnerId(Arrays.asList(paasFormDataEntityExt.getOwnerId()));
            if ( costOpen && costVisible) {
                if (ExplainUtil.invisibleOfScope(costFieldAttrEntity,handlerExplainDTO)) {
                    costVisible = false;
                }
            }
            List<InstockProductEntity> instockProductEntityList = instockProductMap.get(dataId);
            if (instockProductEntityList == null || instockProductEntityList.size() == 0) {
                formDataObj.put(productAttr, new JSONArray());
                continue;
            }
            JSONArray productArray = new JSONArray();
            for (InstockProductEntity instockProductEntity : instockProductEntityList) {
                Long productId = instockProductEntity.getProductId();
                Double num = instockProductEntity.getProductNum() == null ? 0 : instockProductEntity.getProductNum();
                Long warehouseId = instockProductEntity.getWarehouseId();
                if (Objects.nonNull(instockProductEntity.getPriceData()) && instockProductEntity.getPriceData().size() > 0){
                    instockProductEntity.getData().putAll(instockProductEntity.getPriceData());
                }
                Double cost;
                if (Objects.nonNull(instockProductEntity.getPriceData()) && instockProductEntity.getPriceData().size() > 0){
                    cost = instockProductEntity.getData().getDouble(SelectProductEnum.COST.getAttr());
                    num = instockProductEntity.getBusinessNum();
                }else {
                    cost = instockProductEntity.getCost() == null ? 0D : instockProductEntity.getCost();
                }
                // 默认保留两位小数
                cost = Arith.round(cost, accuracy);
                // 产品信息转换
                JSONObject productObj = new JSONObject();
                if (Objects.nonNull(instockProductEntity.getData())) {
                    productObj.putAll(instockProductEntity.getData());
                }
                importHelper.formatProduct4Export(productMap, warehouseMap, productId, num, warehouseId, productObj);
                productObj.put(SelectProductEnum.COST.getAttr(), cost);
                productObj.put(SelectProductEnum.TOTAL_COST.getAttr(), Arith.mul(cost, num));
                if (!costOpen || !costVisible) {
                    productObj.put(SelectProductEnum.COST.getAttr(), null);
                    productObj.put(SelectProductEnum.TOTAL_COST.getAttr(), null);
                }
                //基本单位时直接塞入productUnit
                if (Objects.isNull(instockProductEntity.getBusinessUnit())){
                    if (Objects.equals(productObj.getInteger(ProductEnum.ENABLE_MULTI_UNIT.getAttr()), BasicConstant.ONE)){
                        productObj.put(ProductEnum.UNIT.getAttr(), groupBaseUnitStringMap.getOrDefault(productObj.getString(ProductEnum.UNIT.getAttr()), new MultiUnitItemPoJo()).getBaseValue());
                        instockProductEntity.setProductUnit(productObj.getString(ProductEnum.UNIT.getAttr()));
                    }
                    productObj.put(SelectProductEnum.NUM.getAttr(), instockProductEntity.getProductNum());
                }else {
                    productObj.put(ProductEnum.UNIT.getAttr(), instockProductEntity.getBusinessUnit());
                    productObj.put(SelectProductEnum.NUM.getAttr(), instockProductEntity.getBusinessNum());
                }
                if(Objects.equals(productObj.getInteger(ProductEnum.ENABLE_MULTI_UNIT.getAttr()), BasicConstant.ONE)){
                    productObj.put(SelectProductEnum.BASIC_UNIT.getAttr(), instockProductEntity.getProductUnit());
                    productObj.put(SelectProductEnum.BASIC_UNIT_NUM.getAttr(),  instockProductEntity.getProductNum());
                }else {
                    productObj.put(SelectProductEnum.BASIC_UNIT.getAttr(), "");
                    productObj.put(SelectProductEnum.BASIC_UNIT_NUM.getAttr(), "");
                }
                productArray.add(productObj);
                // 库存产品信息转换
                String batch = instockProductEntity.getBatch();
                productObj.put(SelectProductEnum.BATCH.getAttr(), batch);
                Long guaranteePeriod = instockProductEntity.getGuaranteePeriod();
                if (instockProductEntity.getGuaranteePeriod() != null) {
                    Long guaranteePeriodDay = guaranteePeriod / 86400;
                    if (!Objects.equals(guaranteePeriodDay, 0L)) {
                        productObj.put(SelectProductEnum.GUARANTEE_PERIOD.getAttr(), guaranteePeriodDay);
                    }
                }
                Long produceDate = instockProductEntity.getProduceDate();
                if (produceDate == null || produceDate == 0L) {
                    productObj.put(SelectProductEnum.PRODUCE_DATE.getAttr(), "");
                } else {
                    String produceDateStr = DateTimeUtil.getStringEpochSecond(produceDate, DateTimeUtil.SDFDate);
                    productObj.put(SelectProductEnum.PRODUCE_DATE.getAttr(), produceDateStr);
                    productObj.put(SelectProductEnum.EXPIRE_DATE.getAttr(), DateTimeUtil.getStringEpochSecond(produceDate + guaranteePeriod, DateTimeUtil.SDFDate));
                }
                if (Objects.equals(formDataListDTO.getBusinessType(), XbbRefTypeEnum.REFUND_INSTOCK.getCode())) {
                    productObj.put(SelectProductEnum.PRICE.getAttr(), instockProductEntity.getPrice());
                    productObj.put(SelectProductEnum.SUBTOTAL.getAttr(), Arith.mul(instockProductEntity.getPrice(), num));
                    if (Objects.nonNull(instockProductEntity.getData()) && Objects.nonNull(instockProductEntity.getPriceData()) && instockProductEntity.getPriceData().size() > BasicConstant.ZERO){
                        productObj.put(SelectProductEnum.PRICE.getAttr(), instockProductEntity.getData().get(ProductEnum.PRICE.getAttr()));
                        productObj.put(SelectProductEnum.SUBTOTAL.getAttr(), Arith.mul(instockProductEntity.getData().getDouble(ProductEnum.PRICE.getAttr()), num));
                    }
                }
                String memo = instockProductEntity.getMemo();
                productObj.put(SelectProductEnum.MEMO.getAttr(), memo);

                // 24314 【采购入库单】导出入库产品中关联数据字段展示0.
                if (Objects.equals(formDataListDTO.getBusinessType(), XbbRefTypeEnum.PURCHASE_INSTOCK.getCode())) {
                    for (FieldAttrEntity fieldAttrEntity : fieldAttrList) {
                        if (!PurchaseInstockEnum.PRODUCT.getAttr().equals(fieldAttrEntity.getAttr())) {
                            continue;
                        }
                        SubFormPoJo subForm = fieldAttrEntity.getSubForm();
                        List<FieldAttrEntityForImport> fieldAttrEntityForImports = JSON.parseArray(JSON.toJSONString(subForm.getItems()), FieldAttrEntityForImport.class);
                        for (FieldAttrEntityForImport fieldAttr : fieldAttrEntityForImports) {
                            if (Objects.isNull(fieldAttr.getIsRedundant()) || !BasicConstant.ONE.equals(fieldAttr.getIsRedundant())) {
                                continue;
                            }
                            if (!FieldTypeEnum.LINK_DATA.getType().equals(fieldAttr.getFieldType())) {
                                continue;
                            }
                            String objString = productObj.getString(fieldAttr.getAttr());
                            if (Objects.nonNull(objString) && Objects.equals("0", objString)) {
                                productObj.put(fieldAttr.getAttr(), "");
                            }
                        }
                    }
                }
            }
            formDataObj.put(productAttr, productArray);
        }
    }

    private void updateBatch(InstockUpdateBatchDTO instockUpdateBatchDTO) throws XbbException {
        try {
            List<UpdateDataEntity> updateDataList = new ArrayList<>();
            String corpid = instockUpdateBatchDTO.getCorpid();
            instockUpdateBatchDTO.getOutstockList().forEach((item) -> {
                UpdateDataEntity updateDataEntity = ExplainUtil.getUpdateData(item.getId(), item.getData(), corpid);
                updateDataList.add(updateDataEntity);
            });
            if (!updateDataList.isEmpty()) {
                instockModel.updateBatch(updateDataList, corpid);
            }
        } catch (Exception e) {
            LOG.error("instockService.updateBatch 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    @Override
    public InstockDeleteBatchVO deleteBatch(InstockDeleteBatchDTO instockDeleteBatchDTO) throws XbbException {
        InstockDeleteBatchVO instockDeleteBatchVO = new InstockDeleteBatchVO();
        List<InstockProductEntity> instockProductEntityExts = null;
        boolean isRollBack = false;
        String corpid = instockDeleteBatchDTO.getCorpid();
        List<Long> instockIdList = new ArrayList<>();
        List<String> instockSerialNos = new ArrayList<>();
        //被锁的入库单id
        List<Long> lackIdList;
        try {
            String limit = paasRedisHelper.getValue(RedisPrefixConstant.PRODUCE_STOCK_FLOW, corpid);
            if (StringUtil.isNotEmpty(limit)) {
                throw new XbbException(OutstockErrorCodeEnum.API_ERROR_212036);
            }
            lackIdList = checkRedisKey(corpid,instockDeleteBatchDTO.getDataIdList());
            lackMsg(lackIdList,corpid);
            // 因为待审批和和审批中的数据不存在表中，所以无需校验待审批和审批中的数据
            // 查询入库单
            Map<String, Object> param = BeanUtil.convertBean2Map(instockDeleteBatchDTO, true);
            param.put("del", 0);
            param.put("ids", instockDeleteBatchDTO.getDataIdList());
            List<InstockEntityExt> instockList = instockModel.findEntitys(param);
            if (Objects.isNull(instockList)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            warehouseBoundCheck(instockList,instockDeleteBatchDTO.getDataIdList(),corpid);
            SettleAccountsEntity accountsEntity = settleAccountsModel.getLastSettleAccounts(corpid);
            for (InstockEntityExt instockEntityExt : instockList) {
                Long date = instockEntityExt.getData().getLong(InstockEnum.TIME.getAttr());
                //结账中校验
                String redisHelperValue = paasRedisHelper.getValue(RedisPrefixConstant.SETTLE_ACCOUNTS, corpid);
                if (StringUtil.isNotEmpty(redisHelperValue)) {
                    if (date <= DateTimeUtil.getTodayEndInt(Long.valueOf(redisHelperValue))){
                        throw new XbbException(SettleAccountErrorCodeEnum.API_ERROR_254007);
                    }
                }
                //校验日期是否受结账限制
                if (Objects.nonNull(accountsEntity) && Objects.nonNull(accountsEntity.getCheckOutTime())) {
                    if (date <= DateTimeUtil.getTodayEndInt(accountsEntity.getCheckOutTime())) {
                        throw new XbbException(OutstockErrorCodeEnum.API_ERROR_212032);
                    }
                }
            }
            //查询编号
            Map<Long, String> instockIdAndno= new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for(InstockEntityExt entityExt : instockList){
                Long instockId = entityExt.getId();
                String sheetNo = entityExt.getSerialNo();
                instockIdAndno.put(instockId, sheetNo);
            }

            //现在删除时全都需要查询产品批次保质期序列号状态
            Map<String,Object> instockProductParam = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            instockProductParam.put("instockIdIn", instockDeleteBatchDTO.getDataIdList());
            instockProductParam.put("corpid", instockDeleteBatchDTO.getCorpid());
            instockProductParam.put("del", 0);
            instockProductEntityExts = instockProductModel.findEntitys(instockProductParam);

            // 序列号删除前置校验
            productSerialService.preCheckDelSerial(instockDeleteBatchDTO.getDataIdList(), corpid, instockDeleteBatchDTO.getBusinessType());
            //批次序列号校验
            Set<Long> disableBatchProducts = saasDeleteHelp.checkDocumentDelete(corpid, null, instockProductEntityExts, instockIdAndno);

            Map<String,InstockProductEntity> warehouseKeyMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Map<String,InstockProductEntity> batchKeyMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (InstockProductEntity entity : instockProductEntityExts) {
                entity.setTransferNum(entity.getProductNum());
                if (disableBatchProducts.contains(entity.getParentId())) {
                    String key = entity.getProductId() + "_" + entity.getWarehouseId();
                    if (warehouseKeyMap.containsKey(key)) {
                        InstockProductEntity instockProductEntity = warehouseKeyMap.get(key);
                        instockProductEntity.setTransferNum(Arith.add(instockProductEntity.getTransferNum(),entity.getTransferNum()));
                        warehouseKeyMap.put(key,instockProductEntity);
                    } else {
                        warehouseKeyMap.put(key,entity);
                    }
                } else {
                    String key = formDataValidateProductHelp.getBatchKey(entity.getProductId(), entity.getWarehouseId(), entity.getBatch(), entity.getProduceDate(), entity.getGuaranteePeriod());
                    if (batchKeyMap.containsKey(key)) {
                        InstockProductEntity instockProductEntity = batchKeyMap.get(key);
                        instockProductEntity.setTransferNum(Arith.add(instockProductEntity.getTransferNum(),entity.getTransferNum()));
                        batchKeyMap.put(key,instockProductEntity);
                    } else {
                        batchKeyMap.put(key,entity);
                    }
                }
            }


            //负库存校验
            negativeStockCheck(instockDeleteBatchDTO.getCorpid(), warehouseKeyMap, batchKeyMap);
            boolean isCheck = concurrentLockAspect.checkStock(corpid);
            if (isCheck){
                // 并发时负库存校验
                concurrentLockAspect.delInstockCheck(corpid,instockProductEntityExts, disableBatchProducts);
            }
            isRollBack = true;
            // 如果采购入库单已存在下游单据【采购退货单】，则不允许删除
            for (InstockEntityExt item : instockList) {
                JSONObject data = item.getData();
                Integer type = data.getInteger(InstockEnum.TYPE.getAttr());
                Long refId = data.getLong(InstockEnum.REF_ID.getAttr());
                if (Objects.isNull(refId)) {
                    continue;
                }
                //装配入库单不可以单独删除，要去删除装配单的时候需要一并删除出入库单
                if(Objects.equals(type, InstockTypeEnum.ASSEMBLE_INSTOCK.getCode())){
                    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
                    BoolQueryBuilder boolQueryBuilder = boolQuery();
                    boolQueryBuilder.filter(termQuery("corpid.keyword", instockDeleteBatchDTO.getCorpid()));
                    boolQueryBuilder.filter(termQuery(FieldTypeEnum.DATAID.getAlias(), refId));
                    boolQueryBuilder.filter(termQuery("del", DelEnum.NORMAL.getDel()));
                    // 设置join_field
                    boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, IndexTypeEnum.IDX_SAAS_ASSEMBLE.getType()));
                    searchSourceBuilder.query(boolQueryBuilder);
                    List<PaasFormDataEntityExt> entityExts = paasEsModel.list(searchSourceBuilder, IndexTypeEnum.IDX_SAAS_ASSEMBLE, null, null, null);
                    // 如果装配入库单上有单据装配单未被删除则不允许删除
                    if (Objects.nonNull(entityExts) && entityExts.size() > 0) {
                        throw new XbbException(AssembleErrorCodeEnum.API_ERROR_231020, AssembleErrorCodeEnum.API_ERROR_231020.getMsg());
                    }
                } else if (Objects.equals(type, InstockTypeEnum.PURCHASE_INSTOCK.getCode())) {
                    // 根据【采购入库单】所关联采购合同ID查询是否存在【采购退货单】
                    for (InstockProductEntity instockProductEntityExt : instockProductEntityExts) {
                        if (Objects.nonNull(instockProductEntityExt.getOutstockNum()) && instockProductEntityExt.getOutstockNum() > BasicConstant.ZERO) {
                            instockIdList.add(instockProductEntityExt.getIntoWarehouseId());
                        }
                    }
                }
            }
            if (instockIdList.size() > 0) {
                for (InstockEntityExt instockEntityExt : instockList) {
                    if (instockIdList.contains(instockEntityExt.getId())) {
                        instockSerialNos.add(instockEntityExt.getSerialNo());
                    }
                }
                throw new XbbException(InstockErrorCodeEnum.API_ERROR_210028, String.format(InstockErrorCodeEnum.API_ERROR_210028.getMsg(), instockSerialNos.toString()));
            }

            // 获取恢复产品数量并返回入库类型为采购入库的入库单
            List<InstockEntityExt> purchaseInstockList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            // 合同订单退货入库
            Set<Long> redContractInstockIdSet = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            // 盘点入库单
            List<Long> inventoryInstockList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            // 调拨入库单
            List<Long> transferInstockList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            // 生产成品入库单
            List<InstockEntityExt> finishProductInstockList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            List<Long> finishProductInstockIdList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            // 退料入库单
            List<Long> returnedMaterielInstockIdList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            // 删除入库单
            List<Long> idList = instockDeleteBatchDTO.getDataIdList();
            if(!idList.isEmpty()) {
                if(BasicConstant.ONE.equals(instockDeleteBatchDTO.getSingleFlag()) && BasicConstant.ONE.equals(idList.size())){
                    instockModel.deleteByKey(idList.get(0),corpid);
                } else {
                    instockModel.deleteBatchImmediately(idList, corpid);
                }
                instockDeleteBatchVO.setDeleteIds(idList);
            }
            // 获取入库单的产品并且删除入库单产品
            InstockProductDeleteBatchVO instockProductDeleteBatchVO = findAndDeleteBatchByInstockIdIn(instockDeleteBatchDTO);
            if (Objects.isNull(instockProductDeleteBatchVO)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            // 被删除的入库单产品
            List<InstockProductEntity> instockProductList = instockProductDeleteBatchVO.getInstockProductList();
            Integer type = null;
            for (InstockEntityExt item : instockList) {
                JSONObject jsonObject = item.getData();
                Long refId = jsonObject.getLong(InstockEnum.REF_ID.getAttr());
                if (Objects.isNull(refId)) {
                    // 其他入库单
                    type = InstockTypeEnum.OTHER_INSTOCK.getCode();
                    continue;
                }
                type = jsonObject.getInteger(InstockEnum.TYPE.getAttr());
                InstockTypeEnum instockTypeEnum = InstockTypeEnum.getByCode(type);
                switch (instockTypeEnum) {
                    case PURCHASE_INSTOCK:
                        purchaseInstockList.add(item);
                        break;
                    case RED_CONTRACT_INSTOCK:
                        redContractInstockIdSet.add(refId);
                        break;
                    case INVENTORY_INSTOCK:
                        // 盘点入库单
                        inventoryInstockList.add(refId);
                        break;
                    case TRANSFER_INSTOCK:
                        transferInstockList.add(refId);
                        break;
                    case FINSHED_PRODUCT_INSTOCK:
                        finishProductInstockIdList.add(refId);
                        finishProductInstockList.add(item);
                        break;
                    case RETURNED_MATERIEL_INSTOCK:
                        returnedMaterielInstockIdList.add(refId);
                        break;
                    default:
                        break;
                }
            }
            // 恢复产品数量并返回入库类型为采购入库的入库单
            //并更新采购合同产品表已入库数量
            if (!purchaseInstockList.isEmpty()) {
                getPurchaseProductListMap(instockDeleteBatchDTO, purchaseInstockList,instockProductList);
                // 封装删除单据的产品数量 更新智能补货表数据
                Map<Long, Double> smartProductMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                List<Long> productIdList = new ArrayList<>();
                for (InstockProductEntity entity : instockProductList) {
                    Long productId = entity.getProductId();
                    Double productNum = entity.getProductNum();
                    if(smartProductMap.containsKey(productId)){
                        smartProductMap.put(productId,Arith.add(smartProductMap.get(productId),productNum));
                    }else {
                        smartProductMap.put(productId,productNum);
                        productIdList.add(productId);
                    }
                }
                if (CollectionsUtil.isNotEmpty(productIdList)){
                    List<SmartReplenishmentEntity> smartReplenishmentEntities = smartReplenishmentModel.getByProductList(corpid, productIdList);
                    if (CollectionsUtil.isNotEmpty(smartReplenishmentEntities)){
                        for (SmartReplenishmentEntity entity : smartReplenishmentEntities) {
                            Long productId = entity.getProductId();
                            Double pendingInstockNum = Objects.isNull(entity.getPendingInstockNum()) ? 0D : entity.getPendingInstockNum();
                            if (smartProductMap.containsKey(productId)){
                                Double delNum = smartProductMap.getOrDefault(productId,0D);
                                entity.setPendingInstockNum(Arith.add(delNum,pendingInstockNum));
                            }
                        }
                        try {
                            smartReplenishmentModel.updateBatch(smartReplenishmentEntities,corpid);
                        }catch (Exception e){
                            LOG.error("instockServiceImpl.deleteBatch() 更新智能补货表数据时出错", e);
                            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
                        }
                    }
                }
            }
            // 红冲合同
            if (!redContractInstockIdSet.isEmpty()) {
                // 重置合同入库单
                setRefundInBound(instockDeleteBatchDTO, redContractInstockIdSet, instockProductList);
                // 退货入库单修复合同成本
                if(Objects.equals(type, InstockTypeEnum.RED_CONTRACT_INSTOCK.getCode())){
                    instockHelp.afterSaveRefundInstock4ContractCost(corpid, redContractInstockIdSet, false, null);
                }
            }
            // 删除入库单后重置盘点单入库单Id
            if (!inventoryInstockList.isEmpty()) {
                InventoryResetInstockIdDTO inventoryResetInstockIdDTO = new InventoryResetInstockIdDTO();
                BeanUtil.copyProperties(instockDeleteBatchDTO, inventoryResetInstockIdDTO);
                inventoryResetInstockIdDTO.setIdIn(inventoryInstockList);
                inventoryResetInstockIdDTO.setAttr(InventoryEnum.INSTOCK_ID.getAttr());
                //目前一个盘点单下只能有一个盘盈入库单，故删除盘盈入库单的话，直接修改 入库单id为0即可。
                inventoryService.resetInstockIdByIdIn(inventoryResetInstockIdDTO);
            }
            // 删除入库单后重置调拨单入库单Id
            if (!transferInstockList.isEmpty()) {
                TransferResetInstockIdDTO transferResetInstockIdDTO = new TransferResetInstockIdDTO();
                BeanUtil.copyProperties(instockDeleteBatchDTO, transferResetInstockIdDTO);
                transferResetInstockIdDTO.setIdIn(transferInstockList);
                transferResetInstockIdDTO.setAttr(TransferEnum.INSTOCK_ID.getAttr());
                transferResetInstockIdDTO.setDelInstockIds(idList);
                transferService.updateTransferInstockNum(transferInstockList,corpid,null,instockProductList);
                transferService.resetInstockIdByIdIn(transferResetInstockIdDTO);
            }
            // 生产成品入库单操作
            if (!finishProductInstockList.isEmpty()) {
                updateProductionOrder(instockDeleteBatchDTO, instockProductList, finishProductInstockIdList, finishProductInstockList);
            }
            // 退料入库单
            if (!returnedMaterielInstockIdList.isEmpty()) {
                RetMaterielListDTO retMaterielListDTO = new RetMaterielListDTO();
                BeanUtil.copyProperties(instockDeleteBatchDTO, retMaterielListDTO);
                retMaterielListDTO.setInstockIdIn(returnedMaterielInstockIdList);
                retMaterielListDTO.setDelInstockIdList(instockDeleteBatchDTO.getDataIdList());
                productionOrderService.updateReturnedMaterielInstock(instockProductDeleteBatchVO,retMaterielListDTO,InstockTypeEnum.RETURNED_MATERIEL_INSTOCK.getCode());
            }

            List<Long> childProductIdList = new ArrayList<>();
            childProductIdList.add(-1L);
            Set<Long> warehouseIdList = new HashSet<>();
            for (InstockProductEntity entity : instockProductList){
                childProductIdList.add(entity.getProductId());
                warehouseIdList.add(entity.getWarehouseId());
            }
            try {
                Map<Long,ProductStockUpdateEntity> productAddMap = instockProductService.delUpdateStock(instockProductList,corpid,false, disableBatchProducts);
//                    productService.updateProductStockDown(new HashMap<>(1), childProductIdList,productMap,corpid, false, true);
                productService.updateProductStock(productAddMap,corpid);
                List<StockFlowBillUpdateEntity> stockFlowBillUpdateList = new ArrayList<>();
                List<BatchFlowBillUpdateEntity> batchFlowBillUpdateEntityList = new ArrayList<>();
                Map<Long, Long> timeMap = new HashMap<>(instockList.size());
                instockList.forEach(item -> {
                    timeMap.put(item.getId(), item.getData().getLong(InstockEnum.TIME.getAttr()));
                });
                List<Long> allInstockId = new ArrayList<>();
                List<Long> batchInstockId = new ArrayList<>();
                instockProductList.forEach(item -> {
                    StockFlowBillUpdateEntity stockFlowBillUpdateEntity = new StockFlowBillUpdateEntity(item.getProductId() + "_" + item.getWarehouseId(), Arith.sub(0D, item.getProductNum()),Arith.mul(Arith.sub(0D, item.getProductNum()), item.getCost()), timeMap.get(item.getIntoWarehouseId()), DateTimeUtil.getInt(), item.getIntoWarehouseId());
                    stockFlowBillUpdateList.add(stockFlowBillUpdateEntity);
                    allInstockId.add(item.getIntoWarehouseId());
                    if (StringUtil.isNotEmpty(item.getBatch()) && !disableBatchProducts.contains(item.getParentId())) {
                        BatchFlowBillUpdateEntity batchFlowBillUpdateEntity = new BatchFlowBillUpdateEntity(item.getProductId() + "_" + item.getWarehouseId() + "_" + item.getBatch() + "_" + item.getProduceDate() + "_" + item.getGuaranteePeriod(), Arith.sub(0D, item.getProductNum()),Arith.mul(Arith.sub(0D, item.getProductNum()), item.getCost()), timeMap.get(item.getIntoWarehouseId()), DateTimeUtil.getInt(), item.getIntoWarehouseId());
                        batchFlowBillUpdateEntityList.add(batchFlowBillUpdateEntity);
                        batchInstockId.add(item.getIntoWarehouseId());
                    }
                });
                //发送成本重算信息
                CostRecalculationDTO costRecalculationDTO = new CostRecalculationDTO();
                costRecalculationDTO.setCorpid(corpid);
                costRecalculationDTO.setType(StockTypeEnum.IN_STOCK.getCode());
                costRecalculationDTO.setMark(BasicConstant.TWO);
                costRecalculationDTO.setInstockList(instockList);
                costRecalculationDTO.setStockIdIn(allInstockId);
                costRecalculationDTO.setIsWorkFlow(BasicConstant.ONE);
                costRecalculationDTO.setInstockProductList(instockProductList);
                costRecalculationDTO.setBatchOutStockIdIn(batchInstockId);
                costRecalculationDTO.setStockFlowBillUpdateList(stockFlowBillUpdateList);
                costRecalculationDTO.setBatchFlowBillUpdateEntityList(batchFlowBillUpdateEntityList);
                /*stockFlowBillService.caculateStockModification4Delete(allInstockId, stockFlowBillUpdateList, XbbRefTypeEnum.INSTOCK.getCode(), corpid);
                batchFlowBillService.batchFlowModification4Delete(batchInstockId, batchFlowBillUpdateEntityList, XbbRefTypeEnum.INSTOCK.getCode(), corpid);*/
                oriStockService.reSetWarehouseOriStock(corpid,warehouseIdList);
                costRecalculationProducer.sendMessage(costRecalculationDTO);
            } catch (XbbException e) {
                LOG.error("更新入库单产品分仓库存、批次库存出错",e);
            }
            final Integer instockType = type;
            if (Objects.isNull(instockType)){
                LOG.error("instockDelErr:" + JSONObject.toJSONString(instockDeleteBatchDTO));
                LOG.error("instockDelErrLen:" + instockList.size());
            }
            //TODO 多线程中事务可能不生效 后续需要确认,生成入库单产品步骤可能存在数据不同步的现象待验证
            Runnable runnable = () -> {
                try {
                    //产品分仓库存数量
                    BoolQueryBuilder boolQueryBuilder = boolQuery();
                    boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
                    boolQueryBuilder.filter(termsQuery(ProductWarehouseSubFormEnum.getEsAttr(ProductWarehouseSubFormEnum.PRODUCT_ID), childProductIdList));
                    boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
                    boolQueryBuilder.filter(termQuery(ProductWarehouseSubFormEnum.getEsAttr(ProductWarehouseSubFormEnum.WAREHOUSE_CHECKED), 1));
                    List<String> productWarehouseFieldList = new ArrayList<>();
                    productWarehouseFieldList.add(ProductWarehouseSubFormEnum.getAttrConnectData(ProductWarehouseSubFormEnum.PRODUCT_ID));
                    productWarehouseFieldList.add(ProductWarehouseSubFormEnum.getAttrConnectData(ProductWarehouseSubFormEnum.WAREHOUSE_ID));
                    productWarehouseFieldList.add(ProductWarehouseSubFormEnum.getAttrConnectData(ProductWarehouseSubFormEnum.WAREHOUSE_NAME));
                    productWarehouseFieldList.add(ProductWarehouseSubFormEnum.getAttrConnectData(ProductWarehouseSubFormEnum.NUM));
                    List<PaasFormDataEntity> childProductList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PRODUCT_WAREHOUSE, boolQueryBuilder, PaasFormDataEntity.class, productWarehouseFieldList);
                    List<ProductWarehouseEntity> productWarehouseEntities = transferSubFormHelper.transferFormDataToProductWarehouseList(childProductList);

                    Map<String, ProductWarehouseEntity> instockProductStockMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    productWarehouseEntities.forEach(entityExt -> {
                        String key = entityExt.getProductId() + "_" + entityExt.getWarehouseId();
                        instockProductStockMap.put(key, entityExt);
                    });

                    // 出库单一对多产品
                    Map<Long, List<InstockProductEntity>> instockIdAndListMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    ListIterator<InstockProductEntity> it = instockProductList.listIterator();
                    while (it.hasNext()) {
                        InstockProductEntity instockProduct = it.next();
                        Long instockId = instockProduct.getIntoWarehouseId();
                        List<InstockProductEntity> instockProductEntityList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                        instockProductEntityList.add(instockProduct);

                        if (instockIdAndListMap.get(instockId) == null) {
                            instockIdAndListMap.put(instockId, instockProductEntityList);
                        } else {
                            instockProductEntityList.addAll(instockIdAndListMap.get(instockId));
                            instockIdAndListMap.put(instockId, instockProductEntityList);
                        }
                    }
                    // 各个出库单对应的出库产品
                    Map<Long, List<String>> instockListMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    Iterator<Map.Entry<Long, List<InstockProductEntity>>> inIterator = instockIdAndListMap.entrySet().iterator();
                    while (inIterator.hasNext()) {
                        Map.Entry<Long, List<InstockProductEntity>> entry = inIterator.next();
                        Long instockId = entry.getKey();
                        List<InstockProductEntity> instockProductEntities = entry.getValue();

                        List<String> inProductStrList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                        for (InstockProductEntity instockProduct : instockProductEntities) {
                            Double productNum = instockProduct.getProductNum() == null ? 0D : instockProduct.getProductNum();
                            Double cost = instockProduct.getCost() == null ? 0D : instockProduct.getCost();

                            String key = instockProduct.getProductId() + "_" + instockProduct.getWarehouseId();
                            ProductWarehouseEntity productWarehouseEntity = instockProductStockMap.get(key);
                            // 拼接产品信息
                            String productName = instockProduct.getProductName() == null ? "--" : instockProduct.getProductName();
                            String productNo = instockProduct.getProductNo() == null ? "--" : instockProduct.getProductNo();
                            String productSpecification = Objects.equals(instockProduct.getProductSpecification(), "") ? "--" : instockProduct.getProductSpecification();
                            productSpecification = productSpecification.replaceAll("[`~!@#$%^&*\",.，。【】“”'‘’()+=|{}'.;'\\[\\]<>/?~@#￥%……&*]|\\s*|\t|\r|\n", "");
                            if (productSpecification.contains(":")) {
                                productSpecification = productSpecification.replace(":", "/");
                            }
                            String warehouseName = productWarehouseEntity == null ? "--" : productWarehouseEntity.getWarehouseName();
                            String batch = Objects.equals(instockProduct.getBatch(), "") ? "--" : instockProduct.getBatch();
                            StringBuilder sb = new StringBuilder();
                            sb.append("产品名称：").append(productName).append("，").append("产品编号：").append(productNo).append("，")
                                    .append("规格：").append(productSpecification).append("，").append("仓库：").append(warehouseName).append("，")
                                    .append("入库数量：").append(productNum).append("，").append("成本：").append(cost).append("，")
                                    .append("批次号：").append(batch).append("；<br/>");
                            inProductStrList.add(sb.toString());
                        }
                        instockListMap.put(instockId, inProductStrList);
                    }

                    //生成删除日志(区分单个删除和批量删除)
                    String userId = instockDeleteBatchDTO.getUserId();
                    String userName = instockDeleteBatchDTO.getLoginUserName();
                    List<String> list = new ArrayList<>();
                    // 出入库单流水号不能为空
                    Iterator<Map.Entry<Long, String>> iterator = instockIdAndno.entrySet().iterator();
                    while (iterator.hasNext()) {
                        Map.Entry<Long, String> entry = iterator.next();
                        Long key = entry.getKey();
                        String value = instockIdAndno.get(key);
                        if (instockListMap.containsKey(key)) {
                            List<String> instockProductStrList = instockListMap.get(key);
                            String outstockProductStr = StringUtils.join(instockProductStrList, "，");
                            StringBuilder sb = new StringBuilder();
                            sb.append(value).append("<br/>").append("（").append(outstockProductStr).append("）");
                            list.add(sb.toString());
                        } else {
                            list.add(value);
                        }
                    }
                    OperateTypeEnum operateTypeEnum = OperateTypeEnum.DELETE;
                    if (Objects.equals(1, instockDeleteBatchDTO.getIsBusinessRule())) {
                        operateTypeEnum = OperateTypeEnum.RULE_DELETE;
                    }
                    String nameStr = StringUtils.join(list, "，<br/>");
                    InstockTypeEnum instockTypeEnum = InstockTypeEnum.getByCode(instockType);
                    if (idList.size() > 1) {
                        String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_BATCH_DELETE_FORM_DETAIL), userName, XbbRefTypeEnum.getByCode(instockTypeEnum.getStockBusinessType()).getName(), idList.size());
                        List<InfoArrPojo> infoArrPojoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                        InfoArrPojo infoArrPojo = new InfoArrPojo();
                        infoArrPojo.setTitle(InstockEnum.SHEET_NO.getAttrName());
                        infoArrPojo.setContent(nameStr);
                        infoArrPojoList.add(infoArrPojo);
                        mongoLogHelp.buildLog4InfoArr(infoArrPojoList, corpid, userId, userName, instockTypeEnum.getOperateModuleTypeEnum(), operateTypeEnum,
                                "", "", memo, instockDeleteBatchDTO.getHttpHeader());
                    } else if (Objects.equals(idList.size(), 1)) {
                        Long instockLogId = idList.get(0);
                        String instockLogNo = instockIdAndno.get(instockLogId);
                        String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_DELETE_WORK), userName, XbbRefTypeEnum.getByCode(instockTypeEnum.getStockBusinessType()).getName(), instockLogNo);
                        List<InfoArrPojo> infoArrPojoList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                        InfoArrPojo infoArrPojo = new InfoArrPojo();
                        infoArrPojo.setTitle(InstockEnum.PRODUCT.getAttrName());
                        infoArrPojo.setContent(nameStr);
                        infoArrPojoList.add(infoArrPojo);
                        mongoLogHelp.buildLog4InfoArr(infoArrPojoList, corpid, userId, userName, instockTypeEnum.getOperateModuleTypeEnum(), operateTypeEnum,
                                instockLogId.toString(), instockLogNo, memo, instockDeleteBatchDTO.getHttpHeader());
                    }
                } catch (Exception e) {
                    LOG.error("删除入库单记录日志出错",e);
                }
            };
            threadPoolBeanConfig.addUpdateDelThreadPool().execute(runnable);
        } catch (XbbException e) {
            removeDelLack(instockDeleteBatchDTO.getDataIdList(),corpid);
            if (isRollBack) {
                boolean isCheck = concurrentLockAspect.checkStock(corpid);
                if (isCheck){
                    // 没开启负库存的才需要回滚
                    concurrentLockAspect.deleteInstockStockRollBack(instockProductEntityExts);
                }
            }
            throw e;
        } catch (Exception e) {
            removeDelLack(instockDeleteBatchDTO.getDataIdList(),corpid);
            if (isRollBack) {
                boolean isCheck = concurrentLockAspect.checkStock(corpid);
                if (isCheck){
                    // 没开启负库存的才需要回滚
                    concurrentLockAspect.deleteInstockStockRollBack(instockProductEntityExts);
                }
            }
            LOG.error("instockServiceImpl.deleteBatch 批量删除出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
//        removeDelLack(instockDeleteBatchDTO.getDataIdList(),corpid);
//        lackMsg(lackIdList,corpid);
        return instockDeleteBatchVO;
    }

    private void warehouseBoundCheck(List<InstockEntityExt> instockList, List<Long> instockIdList, String corpid) throws XbbException {
        Map<String,Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.CORPID,corpid);
        param.put(StringConstant.DEL,DelEnum.NORMAL.getDel());
        param.put("intoWarehouseIdIn",instockIdList);
        param.put("orderByStr","product_id,warehouse_id");
        param.put("productDel",0);
        param.put("warehouseDel",0);
        param.put("columns","into_warehouse_id,product_id,warehouse_id,product_name");
        List<InstockProductEntity> instockProductEntityList = instockProductModel.findEntitys(param);
        Set<String> warehouseKeyList = new HashSet<>();
        Map<String,InstockProductEntity> warehouseKeyMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        instockProductEntityList.forEach(item -> {
            warehouseKeyList.add(item.getProductId() + "_" + item.getWarehouseId());
            warehouseKeyMap.put(item.getProductId() + "_" + item.getWarehouseId(),item);
        });
        //出库只查询绑定的分仓
        List<String> existWarehouseKeyList = productWarehouseModel.getExistWarehouseKeyList(corpid, warehouseKeyMap.keySet(),1);
        warehouseKeyList.removeAll(existWarehouseKeyList);
        if (!warehouseKeyList.isEmpty()) {
            for (String warehouseKey : warehouseKeyList) {
                for (InstockEntityExt instockEntityExt : instockList) {
                    InstockProductEntity entity = warehouseKeyMap.get(warehouseKey);
                    if (Objects.isNull(entity)) {
                        continue;
                    }
                    if (Objects.equals(instockEntityExt.getId(),entity.getIntoWarehouseId())) {
                        Long warehouseId = entity.getWarehouseId();
                        String productName = entity.getProductName();
                        WarehouseEntityExt warehouseEntityExt = warehouseModel.getByKey(warehouseId,corpid);
                        throw new XbbException(ProductErrorCodeEnum.API_ERROR_205067,String.format(ProductErrorCodeEnum.API_ERROR_205067.getMsg(),instockEntityExt.getSerialNo(),productName,warehouseEntityExt.getData().getString(WarehouseEnum.WAREHOUSE_NAME.getAttr())));

                    }
                }
            }
        }
    }

    /**
     * 报错后清除缓存锁
     * @param instockIdList
     * @param corpid
     */
    private void removeDelLack(List<Long> instockIdList, String corpid) {
        for (Long instockId : instockIdList) {
            String key = corpid + "_" + instockId;
            paasRedisHelper.removeValue(RedisPrefixConstant.INSTOCK_DEL,key);
        }
    }

    /**
     * 抛出加锁日志
     * @param lackIdList
     * @param corpid
     * @throws XbbException
     */
    private void lackMsg(List<Long> lackIdList, String corpid) throws XbbException {
        if (!lackIdList.isEmpty()){
            Map<String,Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            map.put(StringConstant.CORPID,corpid);
            map.put("idIn",lackIdList);
            map.put("columns","serial_no");
            List<InstockEntityExt> instockEntityExtList = instockModel.findEntitys(map);
            StringBuilder stringBuilder = new StringBuilder();
            instockEntityExtList.forEach(item -> stringBuilder.append(item.getSerialNo()).append(","));
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100404, ErrorMessageConstant.DATA_DEL_LACK_ERROR_MSG,stringBuilder.toString());
        }
    }

    /**
     * 校验删除数据是否有锁
     * @param corpid
     * @param instockIdList
     * @return
     */
    private List<Long> checkRedisKey(String corpid, List<Long> instockIdList) {
        Iterator<Long> iterator = instockIdList.iterator();
        List<Long> lackIdList = new ArrayList<>();
        while (iterator.hasNext()){
            Long instockId = iterator.next();
            String key = corpid + "_" + instockId;
            Long value = paasRedisHelper.getIncrNum(RedisPrefixConstant.INSTOCK_DEL,key, TimeConstant.SECONDS_PER_MINUTE,1,1);
            if (value > 1L){
                lackIdList.add(instockId);
                iterator.remove();
            }
        }
        return lackIdList;
    }

    /**
     * 入库单删除，负库存校验
     * @param corpid 公司id
     * @throws XbbException 负库存提示
     */
    @Override
    public void negativeStockCheck(String corpid, Map<String, InstockProductEntity> warehouseKeyMap, Map<String, InstockProductEntity> batchKeyMap) throws XbbException {
        FormConfigEntity outStockRuleConfigEntity = formConfigModel.getEntityByBusinessType(corpid, XbbRefTypeEnum.OUTSTOCK.getCode(), FormConfigEnum.OUTSTOCK_INSUFFICIENT_NOT_ALLOW_WAREHOUSING.getConfig());
        //部分公司没有配置表示不开启负库存
        if (Objects.nonNull(outStockRuleConfigEntity)) {
            if (!Objects.equals(outStockRuleConfigEntity.getConfigValue(), "1")) {
                return;
            }
        }

            if (!warehouseKeyMap.isEmpty()) {
                BoolQueryBuilder boolQueryBuilder = boolQuery();
                boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
                boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
                boolQueryBuilder.filter(termQuery(ProductWarehouseSubFormEnum.getEsAttr(ProductWarehouseSubFormEnum.WAREHOUSE_CHECKED), 1));
                for (Map.Entry<String, InstockProductEntity> entry : warehouseKeyMap.entrySet()) {
                    InstockProductEntity entity = entry.getValue();
                    BoolQueryBuilder shouldBuilder = boolQuery();
                    shouldBuilder.filter(rangeQuery(ProductWarehouseSubFormEnum.getEsAttr(ProductWarehouseSubFormEnum.NUM)).lt(entity.getTransferNum()));
                    shouldBuilder.filter(termQuery(ProductWarehouseSubFormEnum.getEsAttr(ProductWarehouseSubFormEnum.PRODUCT_ID), entity.getProductId()));
                    shouldBuilder.filter(termQuery(ProductWarehouseSubFormEnum.getEsAttr(ProductWarehouseSubFormEnum.WAREHOUSE_ID), entity.getWarehouseId()));
                    boolQueryBuilder.should(shouldBuilder);
                }
                boolQueryBuilder.minimumShouldMatch(MINI_MUM_SHOULD_MATCH);
                ElasticAggsPojo elasticAggsPojo = esHelper.elasticAggs(IndexTypeEnum.IDX_SAAS_PRODUCT_WAREHOUSE, boolQueryBuilder, null);
                if (StringUtil.toInt(elasticAggsPojo.getTotal(), 0) > 0) {
                    throw new XbbException(InstockErrorCodeEnum.API_ERROR_210038);
                }
            }


            if (!batchKeyMap.isEmpty()) {
                BoolQueryBuilder boolQueryBuilder = boolQuery();
                boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
                boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
                boolQueryBuilder.filter(termQuery(ProductStockSubFormEnum.getEsAttr(ProductStockSubFormEnum.WAREHOUSE_CHECKED), 1));
                for (Map.Entry<String, InstockProductEntity> entry : batchKeyMap.entrySet()) {
                    InstockProductEntity entity = entry.getValue();
                    BoolQueryBuilder shouldBuilder = boolQuery();
                    shouldBuilder.filter(rangeQuery(ProductStockSubFormEnum.getEsAttr(ProductStockSubFormEnum.NUM)).lt(entity.getTransferNum()));
                    shouldBuilder.filter(termQuery(ProductStockSubFormEnum.getEsAttr(ProductStockSubFormEnum.PRODUCT_ID), entity.getProductId()));
                    shouldBuilder.filter(termQuery(ProductStockSubFormEnum.getEsAttr(ProductStockSubFormEnum.WAREHOUSE_ID), entity.getWarehouseId()));
                    shouldBuilder.filter(termQuery(ProductStockSubFormEnum.getEsAttr(ProductStockSubFormEnum.BATCH), entity.getBatch()));
                    shouldBuilder.filter(termQuery(ProductStockSubFormEnum.getEsAttr(ProductStockSubFormEnum.GUARANTEE_PERIOD), entity.getGuaranteePeriod()));
                    shouldBuilder.filter(termQuery(ProductStockSubFormEnum.getEsAttr(ProductStockSubFormEnum.PRODUCE_DATE), entity.getProduceDate()));
                    boolQueryBuilder.should(shouldBuilder);
                }
                boolQueryBuilder.minimumShouldMatch(MINI_MUM_SHOULD_MATCH);
                ElasticAggsPojo elasticAggsPojo = esHelper.elasticAggs(IndexTypeEnum.IDX_SAAS_PRODUCT_STOCK_INFO, boolQueryBuilder, null);
                if (StringUtil.toInt(elasticAggsPojo.getTotal(), 0) > 0) {
                    throw new XbbException(InstockErrorCodeEnum.API_ERROR_210038);
                }
            }

    }

    /**
     * 按照查询条件查找符合条件的数据从ES中
     *
     * @param corpid 公司ID
     * @param refId  关联单据ID
     * @param type   入库类型 1采购入库，2合同订单退货入库，3盘盈入库，4调拨入库，5其他入库，6装配入库
     * @return PaasFormDataEsListVO
     * @date 2019/2/27 19:20
     * @author Jian.Wang
     */
    @Override
    public PaasFormDataEsListVO getInstockListFromEs(String corpid, Long refId, Integer type) throws XbbException {
        return saasInstockHelp.getInstockListFromEs(corpid, refId, type);
    }

    @Override
    public JSONObject getFormatProductJsonArray(FormatInstockProductDTO formatInstockProductDTO) throws XbbException {
        // 获取参数
        String corpid = formatInstockProductDTO.getCorpid();
        UserEntity userEntity = formatInstockProductDTO.getUserEntity();
        InstockProductEntityExt instockProductExt = formatInstockProductDTO.getInstockProductExt();
        Map<String, FieldAttrEntity> nowProductExplainMap = formatInstockProductDTO.getNowProductExplainMap();
        Map<String, FieldAttrEntity> nowStockProductExplainMap = formatInstockProductDTO.getNowStockProductExplainMap();
        JSONObject warehouseObj = instockProductExt.getWarehouseObj();

        Long productId = instockProductExt.getProductId();
        Long productWarehouseId = instockProductExt.getWarehouseId();
        ProductEntityExt childProduct = productModel.getByKey(productId, corpid);
        boolean isCostFieldNeedHide = false;
        if (childProduct != null) {
            Long parentId = childProduct.getData().getLong(ProductEnum.PARENT_ID.getAttr());
            PaasFormDataEntityExt paasFormDataEsEntity = productModel.getByKey(parentId, corpid);
            if (paasFormDataEsEntity != null) {
                //协同团队
                Map<Long, List<String>> mainUserMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                Map<Long, List<String>> coUserMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                userTeamService.getUserIdMap(Collections.singletonList(parentId), corpid, XbbRefTypeEnum.PRODUCT.getCode(), false, mainUserMap, coUserMap);
                HandlerExplainDTO handlerExplainDTO = new HandlerExplainDTO();
                BeanUtil.copyProperties(formatInstockProductDTO, handlerExplainDTO);
                handlerExplainDTO.setCreatorId(paasFormDataEsEntity.getCreatorId());
                handlerExplainDTO.setOwnerId(mainUserMap.getOrDefault(paasFormDataEsEntity.getDataId(), new ArrayList<>()));
                handlerExplainDTO.setCoUserId(coUserMap.getOrDefault(paasFormDataEsEntity.getDataId(), new ArrayList<>()));
                handlerExplainDTO.setExplainList(new ArrayList<>(nowProductExplainMap.values()));
                isCostFieldNeedHide = ExplainUtil.isFieldNeedHide(nowProductExplainMap.getOrDefault(ProductEnum.COST.getSaasAttr(), new FieldAttrEntity()), handlerExplainDTO);
            }
        }

        JSONArray attrArray = new JSONArray();
        JSONObject productObj = new JSONObject();
        // 获取关联产品需要展示的字段
        BusinessProductEnum businessProductEnum = BusinessProductEnum.getByCode(XbbRefTypeEnum.INSTOCK.getCode());
        List<RelativeProductEnum> businessProductEnumList = businessProductEnum.getList();

        ProductWarehouseMapDTO productWarehouseMapDTO = new ProductWarehouseMapDTO();
        BeanUtil.copyProperties(formatInstockProductDTO, productWarehouseMapDTO);
        productWarehouseMapDTO.setAllWarehouse(1);
        productWarehouseMapDTO.setProductId(productId);
        ProductWarehouseMapVO productWarehouseMapVO = warehouseService.getSelectProductWarehouses(productWarehouseMapDTO);
        if (Objects.isNull(productWarehouseMapVO)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        Map<String, JSONArray> warehouseMap = productWarehouseMapVO.getProductWarehouseMap();
        JSONArray warehouseArray = warehouseMap.get(BusinessConstant.ALL_WAREHOUSE_ARRAY);

        for (RelativeProductEnum productEnum : businessProductEnumList) {
            String saasAttr = productEnum.getSaasAttr();
            FieldAttrEntity fieldAttrEntity = null;
            if (nowProductExplainMap.containsKey(saasAttr)) {
                fieldAttrEntity = nowProductExplainMap.get(saasAttr);
            }
            switch (productEnum) {
                case NAME:
                    JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(NAME, instockProductExt.getProductName(), fieldAttrEntity));
                    break;
                case PRODUCT_NO:
                    JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(PRODUCT_NO, instockProductExt.getProductNo(), fieldAttrEntity));
                    break;
                case BARCODE:
                    JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(BARCODE, instockProductExt.getBarcode(), fieldAttrEntity));
                    break;
                case WAREHOUSE:
                    warehouseObj = warehouseObj == null ? new JSONObject() : warehouseObj;
                    JSONObject warehouseResultObj = saasUpdateHelp.formatSelectProduct4Show(WAREHOUSE, warehouseObj, fieldAttrEntity);
                    if(warehouseResultObj != null && !warehouseResultObj.isEmpty()) {
                        warehouseResultObj.put("attrName", "入库仓库");
                        warehouseResultObj.put("warehouseArray", warehouseArray);
                        attrArray.add(warehouseResultObj);
                    }
                    break;
                case NUM:
                    if(Objects.isNull(fieldAttrEntity)) {
                        fieldAttrEntity = new FieldAttrEntity();
                    }
                    FieldAttrEntity stockAttrEntity = nowProductExplainMap.get(ProductEnum.STOCK.getSaasAttr());
                    if(Objects.nonNull(stockAttrEntity)) {
                        fieldAttrEntity.setAccuracy(stockAttrEntity.getAccuracy());
                    }
                    JSONObject numObj = saasUpdateHelp.formatSelectProduct4Show(NUM, Math.abs(instockProductExt.getProductNum()), fieldAttrEntity);
                    if(numObj != null && !numObj.isEmpty()) {
                        numObj.put("attrName", "入库数量");
                        attrArray.add(numObj);
                    }
                    break;
                case COST:
                    JSONObject cost = saasUpdateHelp.formatSelectProduct4Show(COST, instockProductExt.getCost(), fieldAttrEntity);
                    if (cost != null  && !cost.isEmpty()) {
                        if (isCostFieldNeedHide) {
                            cost.put("hideCost", true);
                        }
                        attrArray.add(cost);
                    }
                    break;
                case STOCK:
                    /**/
                    if (Objects.isNull(productWarehouseId)) {
                        JSONObject stockObj = saasUpdateHelp.formatSelectProduct4Show(STOCK, instockProductExt.getStock(), fieldAttrEntity);
                        if (stockObj != null && !stockObj.isEmpty()) {
                            attrArray.add(stockObj);
                        }
                    } else {
                        // 上面时总库存，这里需要展示分仓库存
                        for (int i = 0; i < warehouseArray.size(); i++) {
                            JSONObject jsonObject = warehouseArray.getJSONObject(i);
                            Long warehouseId = jsonObject.getLong(StringConstant.SAAS_LINK_BUSINESS_ID);
                            if (Objects.equals(warehouseId, productWarehouseId)) {
                                Double num = jsonObject.getDouble(StringConstant.NUM);
                                JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(STOCK, num, fieldAttrEntity));
                                // 防止脏数据多条命中
                                break;
                            }
                        }
                    }
                    break;
                case UNIT:
                    // 单位回显 存的key是0,1,2 回显对应的单位
                    String productUnit = instockProductExt.getProductUnit();
                    String unitStr = productModel.getProductUnitTextByValue(productUnit, fieldAttrEntity);
                    JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(UNIT, unitStr, fieldAttrEntity));
                    break;
                case SPECIFICATION:
                    // 格式化规格
                    String specification = specificationModel.joinSpecification(instockProductExt.getProductSpecification());
                    JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(SPECIFICATION, specification, fieldAttrEntity));
                    break;
                case BATCH:
                    JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(BATCH, instockProductExt.getBatch(), fieldAttrEntity));
                    break;
                case GUARANTEE_PERIOD:
                    Double period = instockProductExt.getGuaranteePeriod() == null ? 0D : instockProductExt.getGuaranteePeriod() / (double) 86400;
                    JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(GUARANTEE_PERIOD, period, fieldAttrEntity));
                    break;
                case PRODUCE_DATE:
                    Long productDate = instockProductExt.getProduceDate();
                    String date = productDate == null ? "" : DateTimeUtil.getStringEpochSecond(productDate, DateTimeUtil.SDFDate);
                    JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(PRODUCE_DATE, date, fieldAttrEntity));
                    break;
                case MEMO:
                    JsonHelperUtil.addToJSONArray(attrArray, saasUpdateHelp.formatSelectProduct4Show(MEMO, Objects.toString(instockProductExt.getMemo(), ""), fieldAttrEntity));
                    break;
                case THUMBNAIL:
                    JSONArray defaultImage = new JSONArray(Collections.singletonList(StringConstant.DEFAULT_IMAGES));
                    JSONArray imageList = instockProductExt.getImageUrlArray() == null ? defaultImage : instockProductExt.getImageUrlArray();
                    productObj.put(ProductEnum.THUMBNAIL.getSaasAttr(), imageList);
                    break;
                default:
                    break;
            }
        }
        productObj.put("result", attrArray);
        productObj.put(StringConstant.SAAS_LINK_BUSINESS_ID, instockProductExt.getProductId());
        productObj.put(StringConstant.BUSINESS_PRODUCT_ID, instockProductExt.getId());
        productObj.put("parentId",instockProductExt.getParentId());
        // TODO 库存产品自定义字段的回显
        return productObj;
    }

    /**
     * 获取采购产品容器
     *
     * @param instockDeleteBatchDTO
     * @param purchaseInstockList
     * @throws XbbException
     */
    private void  getPurchaseProductListMap(InstockDeleteBatchDTO instockDeleteBatchDTO, List<InstockEntityExt> purchaseInstockList,List<InstockProductEntity> instockProductList) throws XbbException {
        try {
            String corpid = instockDeleteBatchDTO.getCorpid();
            Set<Long> purchaseIds = new HashSet<>();
            List<Long> instockIdIn = new ArrayList<>();
            purchaseInstockList.forEach((item) -> {
                instockIdIn.add(item.getId());
                JSONObject data = item.getData();
                if (Objects.nonNull(data) && Objects.nonNull(data.get(InstockEnum.REF_ID.getAttr()))) {
                    Long refId = data.getLong(InstockEnum.REF_ID.getAttr());
                    purchaseIds.add(refId);
                }
            });
            PurchaseProductListDTO purchaseProductListDTO = new PurchaseProductListDTO();
            BeanUtil.copyProperties(instockDeleteBatchDTO, purchaseProductListDTO);
            purchaseProductListDTO.setPurchaseSheetIdIn(purchaseIds);
            PurchaseProductListVO purchaseProductListVO = purchaseProductService.findPurchaseProduct(purchaseProductListDTO);
            if (Objects.isNull(purchaseProductListVO)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            Map<Long, List<PurchaseProductEntity>> linePurchaseIdUpdates = new HashMap<>();
            if (!CollectionUtils.isEmpty(instockProductList)) {
                //需要更新采购合同产品已入库数量 的 产品
                Map<Long,Double> refProductIdNum = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                //老数据剩余需要删除处理的入库单产品
                List<InstockProductEntity> oldProductList = new ArrayList<>();
                for (InstockProductEntity instockProductEntity : instockProductList) {
                    Long refProductId = instockProductEntity.getRefProductId();
                    if (refProductId != null) {
                        Double num = Arith.add(instockProductEntity.getProductNum(),
                                refProductIdNum.get(refProductId) == null?0D:refProductIdNum.get(refProductId));
                        refProductIdNum.put(refProductId , num);
                    }else {
                        oldProductList.add(instockProductEntity);
                    }
                }
                //计算合同产品已入库数量
                if (!refProductIdNum.isEmpty()) {
                    Map<String,Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    param.put("corpid", corpid);
                    param.put("purchaseIdIn", purchaseIds);
                    param.put("del", DelEnum.NORMAL.getDel());
                    List<PurchaseProductEntity> contractProductEntityList = purchaseProductModel.findEntitys(param);
                    //新数据都有ref_product_id,才更新已入库数量
                    List<PurchaseProductEntity> updatePurchaseProductList = new ArrayList<>();
                    if(!CollectionUtils.isEmpty(contractProductEntityList)){
                        for (PurchaseProductEntity purchaseProductEntity : contractProductEntityList) {
                            Long id = purchaseProductEntity.getId();
                            Long purchaseId = purchaseProductEntity.getPurchaseSheetId();
                            if (refProductIdNum.containsKey(id)) {
                                Double num = refProductIdNum.getOrDefault(id, 0D);
                                purchaseProductEntity.setInstockNum(num * (-1));
                                purchaseProductEntity.setUpdateTime(DateTimeUtil.getInt());
                                updatePurchaseProductList.add(purchaseProductEntity);
                            }
                            List<PurchaseProductEntity> needLinePurchaseList = null;
                            if(linePurchaseIdUpdates.containsKey(purchaseId)){
                                needLinePurchaseList = linePurchaseIdUpdates.get(purchaseId);
                                needLinePurchaseList.add(purchaseProductEntity);
                            }else {
                                needLinePurchaseList = new ArrayList<>();
                                needLinePurchaseList.add(purchaseProductEntity);
                            }
                            linePurchaseIdUpdates.put(purchaseId,needLinePurchaseList);
                        }
                        if(!updatePurchaseProductList.isEmpty()){
                            //更新采购产品表的已入库数量
                            purchaseProductModel.updateInstock(updatePurchaseProductList, corpid);
                        }
                    }
                }
                if (!oldProductList.isEmpty()) {
//                    老数据逻辑
                    HashSet<Long> instockIds = new HashSet<>();
                    HashSet<Long> oldPurchaseIds = new HashSet<>();
                    Map<Long, List<InstockProductEntity>> instockProductMap = new HashMap<>();
                    Map<Long, List<InstockProductEntity>> purchaseToProduct = new HashMap<>();
                    List<PurchaseProductEntity> updatePurchaseProductList = new ArrayList<>();
                    Map<Object, Double> purchaseInstockNumMap = new HashMap<>();
                    for (InstockProductEntity instockProductEntity : oldProductList) {
                        Long intoWarehouseId = instockProductEntity.getIntoWarehouseId();
                        instockIds.add(intoWarehouseId);
                        List<InstockProductEntity> instockProductEntities = instockProductMap.getOrDefault(intoWarehouseId, new ArrayList<>());
                        instockProductEntities.add(instockProductEntity);
                        instockProductMap.put(intoWarehouseId, instockProductEntities);
                        Double num = purchaseInstockNumMap.getOrDefault(instockProductEntity.getProductId(), 0D);
                        num = Arith.add(instockProductEntity.getProductNum(), num);
                        purchaseInstockNumMap.put(instockProductEntity.getProductId(), num);
                    }
                    purchaseInstockList.forEach((item) ->{
                        if (instockIds.contains(item.getId())) {
                            JSONObject data = item.getData();
                            if (Objects.nonNull(data) && Objects.nonNull(data.get(InstockEnum.REF_ID.getAttr()))) {
                                Long refId = data.getLong(InstockEnum.REF_ID.getAttr());
                                oldPurchaseIds.add(refId);
                                List<InstockProductEntity> instockProductEntityList = instockProductMap.getOrDefault(item.getId(), new ArrayList<>());
                                List<InstockProductEntity> ids = purchaseToProduct.getOrDefault(refId, new ArrayList<>());
                                ids.addAll(instockProductEntityList);
                                purchaseToProduct.put(refId, ids);
                            }
                        }
                    });
                    Map<String,Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    param.put("corpid", corpid);
                    param.put("purchaseIdIn", oldPurchaseIds);
                    param.put("del", DelEnum.NORMAL.getDel());
                    List<PurchaseProductEntity> purchaseProductList = purchaseProductModel.findEntitys(param);

                    if (oldPurchaseIds.size() > 1){
//                    批量删除逻辑
                        for (Long refId : oldPurchaseIds) {
                            List<InstockProductEntity> entities = purchaseToProduct.getOrDefault(refId, new ArrayList<>());
                            for (InstockProductEntity entity : entities) {
                                String key = refId + "" + entity.getProductId();
                                Double num = purchaseInstockNumMap.getOrDefault(key, 0D);
                                num = Arith.add(entity.getProductNum(), num);
                                purchaseInstockNumMap.put(key, num);
                            }
                        }
                        for (PurchaseProductEntity entity : purchaseProductList) {
                            String key = entity.getPurchaseSheetId() + "" + entity.getProductId();
                            Double num = purchaseInstockNumMap.getOrDefault(key, 0D);
//                        删除是减
                            entity.setInstockNum(num * (-1));
                            entity.setUpdateTime(DateTimeUtil.getInt());
                            updatePurchaseProductList.add(entity);
                        }

                    }else {
//                    单个删除逻辑
                        for (PurchaseProductEntity purchaseProductEntity : purchaseProductList) {
                            if (Objects.isNull(purchaseProductEntity.getRefProductId())) {
                                Double instockNum = purchaseProductEntity.getInstockNum();
                                Double amendNum = purchaseInstockNumMap.getOrDefault(purchaseProductEntity.getProductId(), 0D);
                                Double inNum = Arith.sub(instockNum, amendNum);
                                if (inNum >= 0) {
                                    instockNum = inNum;
                                    purchaseInstockNumMap.remove(purchaseProductEntity.getProductId());
                                }else {
                                    purchaseInstockNumMap.put(purchaseProductEntity.getProductId(), Arith.sub(amendNum, instockNum));
                                    instockNum = 0D;
                                }
                                purchaseProductEntity.setInstockNum(instockNum);
                                purchaseProductEntity.setUpdateTime(DateTimeUtil.getInt());
                                updatePurchaseProductList.add(purchaseProductEntity);
                            }
                        }
                    }
                    if(!updatePurchaseProductList.isEmpty()){
                        //更新采购产品表的已入库数量
                        purchaseProductModel.updateBatch(updatePurchaseProductList, corpid);
                    }
                }
        }

            Set<Long> productIdIn = new HashSet<>();
            //合并相同的产品(采购合同可以重复添加同一产品)
            Map<Long, PurchaseProductEntity> purchaseProductMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            if (!purchaseProductListVO.getPurchaseProductList().isEmpty()) {
                purchaseProductListVO.getPurchaseProductList().forEach((item) -> {
                    productIdIn.add(item.getProductId());
                    Long productId = item.getProductId();
                    if (purchaseProductMap.containsKey(productId)) {
                        PurchaseProductEntity mergePurchaseProduct = purchaseProductMap.get(productId);
                        Double mergeNum = Arith.add(mergePurchaseProduct.getProductNum(), item.getProductNum());
                        mergePurchaseProduct.setProductNum(mergeNum);
                        Double totalPrice = Arith.add(mergePurchaseProduct.getProductPrice(), item.getProductPrice() * item.getProductNum());
                        mergePurchaseProduct.setProductPrice(totalPrice);
                        String memo = mergePurchaseProduct.getMemo();
                        if (StringUtils.isNotEmpty(item.getMemo())) {
                            memo += "/" + item.getMemo();
                            mergePurchaseProduct.setMemo(memo);
                        }
                        purchaseProductMap.put(productId, mergePurchaseProduct);
                    } else {
                        item.setProductPrice(item.getProductPrice() * item.getProductNum());
                        purchaseProductMap.put(productId, item);
                    }
                });
            }
            Map<Long, ProductEntityExt> productMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            if (!productIdIn.isEmpty()) {
                ProductListDTO productListDTO = new ProductListDTO();
                BeanUtil.copyProperties(instockDeleteBatchDTO, productListDTO);
                productListDTO.setProductIdIn(productIdIn);
                ProductListVO productListVO = productService.findProductList(productListDTO);
                if (Objects.isNull(productListVO)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
                }
                if (!productListVO.getProductList().isEmpty()) {
                    productListVO.getProductList().forEach((item) -> {
                        productMap.put(item.getId(), item);
                    });
                }
            }
            List<PurchaseProductEntity> purchaseProductList = new ArrayList<>();
            for (PurchaseProductEntity purchaseProduct : purchaseProductMap.values()) {
                if (purchaseProduct.getProductNum() != 0) {
                    purchaseProduct.setProductPrice(Arith.div(purchaseProduct.getProductPrice(), purchaseProduct.getProductNum()));
                }
                ProductEntityExt product = productMap.get(purchaseProduct.getProductId());
                if (product != null) {
                    JSONObject data = product.getData();
                    if (Objects.nonNull(data) && Objects.nonNull(data.get(ProductEnum.BARCODE.getAttr()))) {
                        purchaseProduct.setBarcode(data.getString(ProductEnum.BARCODE.getAttr()));
                    }
                }
                purchaseProductList.add(purchaseProduct);
            }
            if (!purchaseIds.isEmpty()||!linePurchaseIdUpdates.keySet().isEmpty()) {
                Map<Long, Collection> instockIdsMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                Set<Long> instockIds = new HashSet<>();
                Map<String, Object> param = BeanUtil.convertBean2Map(instockDeleteBatchDTO, true);
                param.put("idIn", purchaseIds);
                param.put("del", DelEnum.NORMAL.getDel());
                List<PurchaseEntityExt> purchaseList =  purchaseModel.findEntitys(param);
                if (Objects.isNull(purchaseList)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
                }
                for (PurchaseEntityExt item: purchaseList) {
                    JSONObject data = item.getData();
                    if (Objects.nonNull(data) && Objects.nonNull(data.get(PurchaseEnum.INSTOCK_ID.getAttr()))) {
                        List<Long> instockIdList = JSONObject.parseArray(JSON.toJSONString(data.getJSONArray(PurchaseEnum.INSTOCK_ID.getAttr())), Long.class);
                        Iterator<Long> iterator = instockIdList.iterator();
                        while (iterator.hasNext()) {
                            Long instockId = iterator.next();
                            if (instockIdIn.contains(instockId)) {
                                iterator.remove();
                            }
                        }
                        instockIds.addAll(instockIdList);
                        instockIdsMap.put(item.getId(), instockIdList);
                    }
                }
                InstockProductListDTO instockProductListDTO = new InstockProductListDTO();
                BeanUtil.copyProperties(instockDeleteBatchDTO, instockProductListDTO);
                instockProductListDTO.setInstockIdIn(instockIds);
                InstockProductListVO instockProductListVO = instockProductService.findInstockProductList(instockProductListDTO);
                if (Objects.isNull(instockProductListVO)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
                }
                //把id相同的入库产品的数量叠加，然后采购合同的产品比较，判断采购合同里的产品是否已经全部入库
                Map<Long, Double> instockProductMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                for (InstockProductEntity entity : instockProductListVO.getInstockProductList()) {
                    Long instockId = entity.getIntoWarehouseId();
                    if (instockIdIn.contains(instockId)) {
                        continue;
                    }
                    Long productId = entity.getProductId();
                    if (instockProductMap.get(productId) == null) {
                        instockProductMap.put(productId, entity.getProductNum());
                    } else {
                        instockProductMap.put(productId, Arith.add(entity.getProductNum(), instockProductMap.get(productId)));
                    }
                }
                Iterator<PurchaseProductEntity> iterator = purchaseProductList.iterator();
                while (iterator.hasNext()) {
                    PurchaseProductEntity purchaseProductEntity = iterator.next();
                    for (Map.Entry<Long, Double> entry : instockProductMap.entrySet()) {
                        if (purchaseProductEntity.getProductId().equals(entry.getKey())) {
                            //获取剩余未入库数量
                            double leftNum = Arith.sub(purchaseProductEntity.getProductNum(), entry.getValue());
                            if (Double.compare(leftNum, 0D) <= 0) {
                                //如果采购合同产品数量少于已入库数量，那么就将该产品去掉不显示.（出现这种情况是因为采购合同重新编辑数量变少了）
                                iterator.remove();
                                break;
                            } else {
                                purchaseProductEntity.setProductNum(leftNum);
                            }
                        }
                    }
                }
                Map<Long, List<PurchaseProductEntity>> purchaseProductListMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                if (!purchaseProductList.isEmpty()) {
                    for (PurchaseProductEntity purchaseProductEntity : purchaseProductList) {
                        Long purchaseId = purchaseProductEntity.getPurchaseSheetId();
                        if (purchaseProductListMap.containsKey(purchaseId)) {
                            List<PurchaseProductEntity> resultList = purchaseProductListMap.get(purchaseProductEntity.getPurchaseSheetId());
                            resultList.add(purchaseProductEntity);
                            purchaseProductListMap.put(purchaseId, resultList);
                        } else {
                            List<PurchaseProductEntity> resultList = new ArrayList<>();
                            resultList.add(purchaseProductEntity);
                            purchaseProductListMap.put(purchaseId, resultList);
                        }
                    }
                }

                updatePurchase(instockDeleteBatchDTO, purchaseIds, instockIdsMap, purchaseProductListMap,linePurchaseIdUpdates);
            }
        } catch (XbbException e) {
            LOG.error("InstockServiceImpl.getPurchaseProductListMap 执行出错：", e);
            throw e;
        } catch (Exception e) {
            LOG.error("InstockServiceImpl.getPurchaseProductListMap 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    /**
     * 批量更新采购数据
     *
     * @param instockDeleteBatchDTO  前端传参
     * @param purchaseIds            采购id列表
     * @param instockIdsMap          入库单id列表
     * @param purchaseProductListMap 采购产品列表容器
     * @throws XbbException
     */
    private void updatePurchase(InstockDeleteBatchDTO instockDeleteBatchDTO, Set<Long> purchaseIds,
                                Map<Long, Collection> instockIdsMap, Map<Long, List<PurchaseProductEntity>> purchaseProductListMap, Map<Long, List<PurchaseProductEntity>> linePurchaseIdUpdates) throws XbbException {
        try {
            PurchaseListDTO purchaseListDTO = new PurchaseListDTO();
            BeanUtil.copyProperties(instockDeleteBatchDTO, purchaseListDTO);
            List<Long> delDataIdList = instockDeleteBatchDTO.getDataIdList();
            purchaseListDTO.setIdIn(purchaseIds);
            PurchaseListVO purchaseListVO = purchaseService.findPurchaseList(purchaseListDTO);
            if (Objects.isNull(purchaseListVO)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            List<PurchaseUpdateDTO> purchaseList = new ArrayList<>();
            for (PurchaseEntityExt item : purchaseListVO.getPurchaseList()) {
                String corpid = item.getCorpid();
                PurchaseUpdateDTO purchaseUpdateDTO = new PurchaseUpdateDTO();
                purchaseUpdateDTO.setId(item.getId());
                JSONObject purchaseData = item.getData();
                if (Objects.isNull(purchaseData)) {
                    continue;
                }
                JSONObject data = new JSONObject();
                if (instockIdsMap.containsKey(item.getId())) {
                    List<Long> instockIdList = new ArrayList<>(instockIdsMap.get(item.getId()));
                    data.put(PurchaseEnum.INSTOCK_ID.getAttr(), instockIdList);
                }
                String receiveStatus = FastJsonHelper.getStringOrDefaultFromFormData(purchaseData, PurchaseEnum.RECEIVE_STATUS.getAttr(), ReceiveStatusEnum.UNRECEIVED.getCode());
                if (purchaseProductListMap.containsKey(item.getId())) {
                    List<PurchaseProductEntity> purchaseProductEntityList = purchaseProductListMap.get(item.getId());
                    if (purchaseProductEntityList.size() < 1 && purchaseData.getInteger(PurchaseEnum.ALL_INCOMING.getAttr()) == 0) {
                        // 已全部入库
                        data.put(PurchaseEnum.ALL_INCOMING.getAttr(), 1);
                        // 已入库
                        data.put(PurchaseEnum.STATUS.getAttr(), PurchaseStatusEnum.INSTOCK.getCode());
                    } else if (purchaseProductEntityList.size() > 0 && !linePurchaseIdUpdates.containsKey(item.getId())) {
                        data.put(PurchaseEnum.ALL_INCOMING.getAttr(), 0);
                        // 已到货
                        data.put(PurchaseEnum.STATUS.getAttr(), PurchaseStatusEnum.ARRIVED.getCode());
                        //老数据需要去查看是否有其他采购入库单
                        if (!Objects.equals(receiveStatus, ReceiveStatusEnum.CLOSED.getCode())) {
                            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
                            BoolQueryBuilder boolQueryBuilder = boolQuery();
                            boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
                            boolQueryBuilder.filter(termQuery(InstockEnum.getEsAttr4Keyword(InstockEnum.TYPE), InstockTypeEnum.PURCHASE_INSTOCK.getCode()));
                            boolQueryBuilder.filter(termQuery(InstockEnum.getEsAttr4Keyword(InstockEnum.REF_ID), item.getId()));
                            boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
                            boolQueryBuilder.mustNot(termsQuery(FieldTypeEnum.DATAID.getAlias(), delDataIdList));
                            boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, IndexTypeEnum.IDX_SAAS_INSTOCK.getType()));
                            sourceBuilder.query(boolQueryBuilder);
                            sourceBuilder.sort(new FieldSortBuilder("addTime").order(SortOrder.DESC));
                            PageRequest pageRequest = EsUtil.setPage(sourceBuilder, 1, 1);
                            SearchRequest searchRequest = new SearchRequest(IndexTypeEnum.IDX_SAAS_INSTOCK.getIndex());
                            searchRequest.source(sourceBuilder);
                            XbbAggregatedPage<PaasFormDataEntityExt> paasFormDataEntityExts = xbbElasticsearchRestTemplate.queryForPages(pageRequest, searchRequest, PaasFormDataEntityExt.class);
                            if (paasFormDataEntityExts.getTotalElements() > 0) {
                                data.put(PurchaseEnum.RECEIVE_STATUS.getAttr(), ReceiveStatusEnum.PARTIAL.getCode());
                            } else {
                                data.put(PurchaseEnum.RECEIVE_STATUS.getAttr(), ReceiveStatusEnum.UNRECEIVED.getCode());
                            }
                        }
                    }
                }
                if(linePurchaseIdUpdates.containsKey(item.getId())){
                    if (!Objects.equals(receiveStatus, ReceiveStatusEnum.CLOSED.getCode())) {
                        //新数据查看instocknum跟新入库状态
                        List<PurchaseProductEntity> purchaseProductEntities = linePurchaseIdUpdates.get(item.getId());
                        data.put(PurchaseEnum.RECEIVE_STATUS.getAttr(),ReceiveStatusEnum.UNRECEIVED.getCode());
                        for (PurchaseProductEntity purchaseProductEntity : purchaseProductEntities) {
                            if (purchaseProductEntity.getInstockNum() > 0) {
                                data.put(PurchaseEnum.RECEIVE_STATUS.getAttr(),ReceiveStatusEnum.PARTIAL.getCode());
                                break;
                            }
                        }
                    }
                    data.put(PurchaseEnum.ALL_INCOMING.getAttr(), 0);
                    // 已到货
                    data.put(PurchaseEnum.STATUS.getAttr(), PurchaseStatusEnum.ARRIVED.getCode());
                }

                // data 为空时，不更新
                if (data.isEmpty()) {
                    continue;
                }
                purchaseUpdateDTO.setData(data);
                purchaseList.add(purchaseUpdateDTO);
            }
            if (!purchaseList.isEmpty()) {
                PurchaseUpdateBatchDTO purchaseUpdateBatchDTO = new PurchaseUpdateBatchDTO();
                BeanUtil.copyProperties(instockDeleteBatchDTO, purchaseUpdateBatchDTO);
                purchaseUpdateBatchDTO.setPurchaseList(purchaseList);
                purchaseService.updateBatch(purchaseUpdateBatchDTO);
            }
        } catch (XbbException e) {
            LOG.error("InstockServiceImpl.updatePurchase 执行出错：", e);
            throw e;
        } catch (Exception e) {
            LOG.error("InstockServiceImpl.updatePurchase 执行出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }


    /**
     * 批量更新生产单数据
     *
     * @param instockDeleteBatchDTO      前端传入数据
     * @param instockProductList         产品入库单列表
     * @param finishProductInstockIdList 已完成产品入库单id列表
     * @param finishProductInstockList   已完成产品入库单列表
     * @throws XbbException
     */
    private void updateProductionOrder(InstockDeleteBatchDTO instockDeleteBatchDTO, List<InstockProductEntity> instockProductList,
                                       List<Long> finishProductInstockIdList, List<InstockEntityExt> finishProductInstockList) throws XbbException {
        try {
            ProductionOrderListDTO productionOrderListDTO = new ProductionOrderListDTO();
            BeanUtil.copyProperties(instockDeleteBatchDTO, productionOrderListDTO);
            productionOrderListDTO.setRefIdIn(finishProductInstockIdList);
            ProductionOrderListVO productionOrderListVO = productionOrderService.findProductionOrderList(productionOrderListDTO);
            if (Objects.isNull(productionOrderListVO)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            List<ProductionOrderEntityExt> productionOrderList = productionOrderListVO.getProductionOrderList();
            Map<Long, ProductionOrderEntityExt> productionOrderMap = new HashMap<>(finishProductInstockList.size());
            productionOrderList.forEach((item) -> {
                productionOrderMap.put(item.getId(), item);
            });
            //  已完成产品入库单
            Map<Long, InstockEntityExt> finishProductInstockMap = new HashMap<>(finishProductInstockList.size());
            finishProductInstockList.forEach((item) -> {
                finishProductInstockMap.put(item.getId(), item);
            });
            // 入库单产品
            List<ProductionOrderUpdateDTO> productionOrderUpdateList = new ArrayList<>();
            Map<Long , Double> instockIdNum = new HashMap<>();
            instockProductList.forEach((item) -> {
                Long intoWarehouseId = item.getIntoWarehouseId();
                if(instockIdNum.containsKey(intoWarehouseId)){
                    instockIdNum.put(intoWarehouseId, Arith.add(instockIdNum.get(intoWarehouseId),item.getProductNum()));
                }else {
                    instockIdNum.put(intoWarehouseId,item.getProductNum());
                }
            });
            //支持批量删除
            Map<Long , Double> productionOrderIdNum = new HashMap<>();
            finishProductInstockList.forEach((item) -> {
                JSONObject jsonObject = item.getData();
                Long refId = jsonObject.getLong(InstockEnum.REF_ID.getAttr());
                Long id = item.getId();
                if(instockIdNum.containsKey(id)){
                    Double num = instockIdNum.get(id);
                    if(productionOrderIdNum.containsKey(refId)){
                        num = Arith.add(num,productionOrderIdNum.get(refId)==null?0L:productionOrderIdNum.get(refId));
                    }
                    productionOrderIdNum.put(refId , num);
                }
            });

            for(ProductionOrderEntityExt item : productionOrderList) {
                if(productionOrderIdNum.containsKey(item.getId())){
                    JSONObject productionOrderData = item.getData();
                    Double productInstockNum = productionOrderData.getDouble(ProductionOrderEnum.PRODUCT_INSTOCK_NUM.getAttr()) == null ? 0 : productionOrderData.getDouble(ProductionOrderEnum.PRODUCT_INSTOCK_NUM.getAttr());
                    productInstockNum = Arith.sub(productInstockNum, productionOrderIdNum.get(item.getId()));
                    ProductionOrderUpdateDTO updateProductOrder = new ProductionOrderUpdateDTO();
                    updateProductOrder.setId(item.getId());
                    JSONObject data = new JSONObject();
                    data.put(ProductionOrderEnum.PRODUCT_INSTOCK_NUM.getAttr(),productInstockNum);
                    Double productNum = productionOrderData.getDouble(ProductionOrderEnum.PRODUCT_NUM.getAttr()) == null ? 0 : productionOrderData.getDouble(ProductionOrderEnum.PRODUCT_NUM.getAttr());
                    // 未入库数量 = 总数量-已入库数据
                    Double productUnInstockNum = Arith.sub(productNum, productInstockNum);
                    data.put(ProductionOrderEnum.PRODUCT_UNINSTOCK_NUM.getAttr(), productUnInstockNum);
                    JSONArray idsArray = productionOrderData.getJSONArray(ProductionOrderEnum.INSTOCK_ID.getAttr());
                    if (Objects.isNull(idsArray)) {
                        idsArray = new JSONArray();
                    }
                    List<Long> list = JSONObject.parseArray(idsArray.toJSONString(),Long.class);
                    if (!idsArray.isEmpty()) {
                        //删除入库单ids
                        list.removeIf(finishProductInstockMap::containsKey);
                    }
                    data.put(ProductionOrderEnum.INSTOCK_ID.getAttr(), JSON.parseArray(JSON.toJSONString(list)));
                    data.put(ProductionOrderEnum.ALL_INCOMING.getAttr(), 0);
                    updateProductOrder.setData(data);
                    productionOrderUpdateList.add(updateProductOrder);
                }
            }
            ProductionOrderUpdateBatchDTO productionOrderUpdateBatchDTO = new ProductionOrderUpdateBatchDTO();
            BeanUtil.copyProperties(instockDeleteBatchDTO, productionOrderUpdateBatchDTO);
            productionOrderUpdateBatchDTO.setProductionOrderList(productionOrderUpdateList);
            productionOrderService.updateBatchImmediately(productionOrderUpdateBatchDTO);
        } catch (Exception e) {
            LOG.error("instockServiceImpl.updateProductionOrder 更新生成单出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    /**
     * 清除退货退款的已删除的入库单id
     *
     * @param instockDeleteBatchDTO
     * @param redContractInstockIdSet
     * @param instockProductEntityList 被删除的入库单关联的产品
     * @throws XbbException
     */
    private void setRefundInBound(InstockDeleteBatchDTO instockDeleteBatchDTO, Set<Long> redContractInstockIdSet, List<InstockProductEntity> instockProductEntityList) throws XbbException {
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        String corpid = instockDeleteBatchDTO.getCorpid();
        String esData = StringConstant.JSON_DATA + StringConstant.POINT;
        if (Objects.nonNull(redContractInstockIdSet) && !redContractInstockIdSet.isEmpty()) {
            boolQueryBuilder.filter(termsQuery(StringConstant.DATA_ID, redContractInstockIdSet));
        }

        boolQueryBuilder.filter(termQuery(StringConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, corpid));
        boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
        List<String> fieldList = new ArrayList<>();
        fieldList.add(StringConstant.DATA_ID);
        fieldList.add(esData + RefundEnum.INSTOCK_ID.getAttr());
        fieldList.add(esData + RefundEnum.RED_CONTRACT_ID.getAttr());
        fieldList.add(esData + RefundEnum.REFUND_STATUS.getAttr());
        List<PaasFormDataEntityExt> refundList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_REFUND, boolQueryBuilder, PaasFormDataEntityExt.class, fieldList);
        if (Objects.isNull(refundList)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        Map<Long, List<Long>> refundInstockIdMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        //获取红冲合同id
        HashSet<Long> redContractIds = new HashSet<>();
        HashMap<Long, Long> redContractIdtoRefundId = new HashMap<>();
        //获取退货退款单据
        HashMap<Long,String> refundObjects = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        refundList.forEach(item->{
            Long redContractId = item.getData().getLong(RefundEnum.RED_CONTRACT_ID.getAttr());
            redContractIds.add(redContractId);
            refundObjects.put(item.getDataId(),item.getData().getString(RefundEnum.REFUND_STATUS.getAttr()));
            redContractIdtoRefundId.put(redContractId, item.getDataId());
        });
        refundList.forEach(item->{
            if (refundInstockIdMap.containsKey(item.getDataId())) {
                List<Long> refundInstockIdList = refundInstockIdMap.get(item.getDataId());
                if (Objects.nonNull(item.getData()) && Objects.nonNull(item.getData().get(RefundEnum.INSTOCK_ID.getAttr()))) {
                    JSONArray instockId = item.getData().getJSONArray(RefundEnum.INSTOCK_ID.getAttr());
                    List<Long> instockIdList = JSONArray.parseArray(JSON.toJSONString(instockId), Long.class);
                    refundInstockIdList.addAll(instockIdList);
                    refundInstockIdMap.put(item.getDataId(), refundInstockIdList);
                }
            } else {
                if (Objects.nonNull(item.getData()) && Objects.nonNull(item.getData().get(RefundEnum.INSTOCK_ID.getAttr()))) {
                    JSONArray instockId = item.getData().getJSONArray(RefundEnum.INSTOCK_ID.getAttr());
                    List<Long> refundInstockIdList = JSONArray.parseArray(JSON.toJSONString(instockId), Long.class);
                    refundInstockIdMap.put(item.getDataId(), refundInstockIdList);
                }
            }
        });
        Iterator<List<Long>> iterator = refundInstockIdMap.values().iterator();
        while (iterator.hasNext()) {
            List<Long> instockIdIn = iterator.next();
            Iterator<Long> listIterator = instockIdIn.iterator();
            while (listIterator.hasNext()) {
                Long instockId = listIterator.next();
                if (instockDeleteBatchDTO.getDataIdList().contains(instockId)) {
                    // 去掉删除的入库单id
                    listIterator.remove();
                }
            }
        }
        List<RefundUpdateDTO> refundUpdateList = new ArrayList<>();
        if (Objects.nonNull(redContractInstockIdSet)) {
            redContractInstockIdSet.forEach((item) -> {
                if (Objects.nonNull(refundInstockIdMap.get(item))) {
                    RefundUpdateDTO refundUpdateDTO = new RefundUpdateDTO();
                    refundUpdateDTO.setId(item);
                    JSONObject data = new JSONObject();
                    data.put(RefundEnum.ALL_IN_BOUND.getAttr(), 0);
                    List<Long> instockIdList = refundInstockIdMap.get(item);
                    //先去判断退货退款状态是否是已关闭状态
                    if (refundObjects.containsKey(item)) {
                        String refundStatus = refundObjects.get(item);
                        if (!Objects.equals(refundStatus, RefundStatusEnum.CLOSED.getCode())) {
                            data.put(RefundEnum.REFUND_STATUS.getAttr(),RefundStatusEnum.UNREFUND.getCode());
                            if(!instockIdList.isEmpty()){
                                data.put(RefundEnum.REFUND_STATUS.getAttr(),RefundStatusEnum.PARTIAL.getCode());
                            }
                        }
                    }
                    data.put(RefundEnum.INSTOCK_ID.getAttr(), instockIdList == null ? new ArrayList<>() : instockIdList);
                    refundUpdateDTO.setData(data);
                    refundUpdateList.add(refundUpdateDTO);
                }
            });
        }
        if (!refundUpdateList.isEmpty()) {
            RefundUpdateBatchDTO refundUpdateBatchDTO = new RefundUpdateBatchDTO();
            BeanUtil.copyProperties(instockDeleteBatchDTO, refundUpdateBatchDTO);
            refundUpdateBatchDTO.setRefundUpdateList(refundUpdateList);
            refundService.updateBatchImmediately(refundUpdateBatchDTO);
        }

        //需要更新合同产品已入库数量map
        Map<Long,Double> refProductIdNum = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        HashSet<Long> oldInstockIds = new HashSet<>();
        for(InstockProductEntity instockProductEntity : instockProductEntityList){
            if(instockProductEntity.getRefProductId()!=null){
                Long key = instockProductEntity.getRefProductId();
                Double num = refProductIdNum.getOrDefault(key, 0D);
                num += instockProductEntity.getProductNum();
                refProductIdNum.put(key, num);
            }else {
                oldInstockIds.add(instockProductEntity.getIntoWarehouseId());
            }
        }
        Map<String,Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpid", corpid);
        param.put("contractIdIn", redContractIds);
        param.put("type",XbbRefTypeEnum.REFUND.getCode());
        param.put("del", 0);
        List<ContractProductEntity> contractProductEntityList = contractProductModel.findEntitys(param);
        if(!refProductIdNum.isEmpty()){
            // 拿到合同的所有产品
            List<ContractProductEntity> updateList = new ArrayList<>();
            for(ContractProductEntity contractProductEntity : contractProductEntityList){
                if(refProductIdNum.containsKey(contractProductEntity.getId())){
                    contractProductEntity.setInstockNum(Arith.sub(contractProductEntity.getInstockNum(),refProductIdNum.get(contractProductEntity.getId())));
                    updateList.add(contractProductEntity);
                }
            }
            //更新合同产品已出库数量
            if(!updateList.isEmpty()){
                contractProductModel.updateBatchImmediately(updateList,corpid);
            }
        }
        if (!oldInstockIds.isEmpty()) {
//            老数据逻辑
            param.clear();
            param.put("corpid", corpid);
            param.put("idIn", oldInstockIds);
            List<InstockEntityExt> entitys = instockModel.findEntitys(param);
            HashMap<Long, Long> instockToContractId = new HashMap<>();
            HashSet<Long> oldRefundIds = new HashSet<>();
            for (InstockEntityExt entity : entitys) {
                Long contractId = entity.getData().getLong(InstockEnum.REF_ID.getAttr());
                instockToContractId.put(entity.getId(), contractId);
                oldRefundIds.add(contractId);
            }
            Map<Object,Double> oldProductIdNum = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (InstockProductEntity entity : instockProductEntityList) {
                if (oldInstockIds.contains(entity.getIntoWarehouseId())) {
                    Long contractId = instockToContractId.getOrDefault(entity.getIntoWarehouseId(), 0L);
                    String key = contractId + "" + entity.getProductId();
                    Double num = oldProductIdNum.getOrDefault(key, 0D);
                    num += entity.getProductNum();
                    oldProductIdNum.put(key, num);
                }
            }
            for (ContractProductEntity entity : contractProductEntityList) {
                Long refundId = redContractIdtoRefundId.getOrDefault(entity.getContractId(), 0L);
                if (oldRefundIds.contains(refundId)) {
                    String key = refundId + "" + entity.getProductId();
                    Double amendNum = oldProductIdNum.getOrDefault(key, 0D);
                    Double instockNum;
                    if (Arith.sub(entity.getInstockNum(), amendNum) > 0){
                        instockNum = Arith.sub(entity.getInstockNum(), amendNum);
                        oldProductIdNum.remove(key);
                    }else {
                        instockNum = 0D;
                        oldProductIdNum.put(key, Arith.sub(amendNum, entity.getInstockNum()));
                    }
                    entity.setInstockNum(instockNum);
                }
            }
            if(!contractProductEntityList.isEmpty()){
                contractProductModel.updateBatchImmediately(contractProductEntityList,corpid);
            }
        }
    }

    /**
     * 获取入库单产品删除入库单产品
     *
     * @param instockDeleteBatchDTO
     * @return void
     * @throws XbbException 业务异常
     * @author 吴峰
     * @date 2019/2/28 23:23
     */
    private InstockProductDeleteBatchVO findAndDeleteBatchByInstockIdIn(InstockDeleteBatchDTO instockDeleteBatchDTO) throws XbbException {
        InstockProductDeleteBatchVO instockProductDeleteBatchVO;
        try {
            // 删除入库单产品
            List<Long> idList = instockDeleteBatchDTO.getDataIdList();
            InstockProductDeleteBatchDTO instockProductDeleteBatchDTO = new InstockProductDeleteBatchDTO();
            BeanUtil.copyProperties(instockDeleteBatchDTO, instockProductDeleteBatchDTO);
            instockProductDeleteBatchDTO.setInstockIdIn(idList);
            instockProductDeleteBatchVO = instockProductService.deleteBatchByInstockIdIn(instockProductDeleteBatchDTO);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOG.error("instockServiceImpl.deleteBatchByInstockIdIn 批量删除出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return instockProductDeleteBatchVO;
    }


    @Override
    public void dataConsistencyUpdateWarehouse(String corpid, Long dataId, String name) throws XbbException {
        try {
            BoolQueryBuilder filter = boolQuery()
                    .filter(termQuery("corpid.keyword", corpid))
                    .filter(termQuery("del", 0))
                    .filter(termQuery("data." + InstockEnum.WAREHOUSE_ID.getAttr(), dataId));
            List<String> fieldList = new ArrayList<>();
            fieldList.add(FieldTypeEnum.DATAID.getAlias());
            List<PaasFormDataEntityExt> esEntities = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_INSTOCK, filter, PaasFormDataEntityExt.class, fieldList);
            Set<Long> ids = new HashSet<>();
            for (PaasFormDataEntityExt esEntity : esEntities) {
                ids.add(esEntity.getDataId());
            }
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("corpid", corpid);
            param.put("idIn", ids);
            param.put("del", 0);
            List<InstockEntityExt> instockEntityExts = instockModel.findEntitys(param);
            if (Objects.nonNull(instockEntityExts) && !instockEntityExts.isEmpty()) {
                List<InstockUpdateDTO> instockUpdateDTOList = new ArrayList<>();
                for (InstockEntityExt entityExt : instockEntityExts) {
                    JSONObject data = new JSONObject();
                    data.put(InstockEnum.WAREHOUSE_ID_LINKED_TEXT.getAttr(), name);
                    InstockUpdateDTO instockUpdateDTO = new InstockUpdateDTO();
                    instockUpdateDTO.setId(entityExt.getId());
                    instockUpdateDTO.setData(data);
                    instockUpdateDTOList.add(instockUpdateDTO);
                }

                InstockUpdateBatchDTO instockUpdateBatchDTO = new InstockUpdateBatchDTO();
                instockUpdateBatchDTO.setCorpid(corpid);
                instockUpdateBatchDTO.setOutstockList(instockUpdateDTOList);
                updateBatch(instockUpdateBatchDTO);
            }

        } catch (Exception e) {
            LOG.error("InstockServiceImpl.dataConsistencyUpdateWarehouse 出错， corpid=" + corpid + "  warehouseId=" + dataId + "  warehouseName=" + name, e);
        }
    }

    @Override
    public ProductSummaryVO summaryProductList(BusinessProductListDTO businessProductListDTO) throws XbbException {
        // 获取参数
        String corpid = businessProductListDTO.getCorpid();
        Long dataId = businessProductListDTO.getDataId();

        Map<String, Object> modelMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        modelMap.put(ParameterConstant.CORPID, corpid);
        modelMap.put("intoWarehouseId", dataId);
        modelMap.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        modelMap.put("columns", "product_num,rate");
        List<InstockProductEntity> instockProductEntities = instockProductModel.findEntitys(modelMap);

        ProductSummaryVO businessProductListVO = new ProductSummaryVO();

        Double num = 0D;
        Double rate;
        for (InstockProductEntity productEntity : instockProductEntities) {
            rate = productEntity.getRate() == null ? 1D : productEntity.getRate();
            Double productNum = productEntity.getProductNum() != null ? productEntity.getProductNum(): 0D;
            num = Arith.add(num, Arith.div(productNum, rate));
        }
        Integer productSize = instockProductEntities.size();
        String summaryInfo = String.format(I18nMessageUtil.getMessage(StringConstant.PRODUCTS_TYPE_NUM), productSize, Arith.doubleToBigDecimal(num));
        businessProductListVO.setSummaryInfo(summaryInfo);
        return businessProductListVO;
    }

    @Override
    public void updateBatchByBusinessRule(InstockUpdateByBusinessRuleDTO instockUpdateByBusinessRuleDTO) throws XbbException {
        try {
            String corpid = instockUpdateByBusinessRuleDTO.getCorpid();
            List<PaasFormDataEntityExt> formDataList = instockUpdateByBusinessRuleDTO.getFormDataList();
            List<UpdateDataEntity> updateList = ExplainUtil.getUpdateValueByBusinessRule(instockUpdateByBusinessRuleDTO.getFormDataList(), corpid, instockUpdateByBusinessRuleDTO.getOperations());

            if (!updateList.isEmpty()) {
                instockModel.updateBatch(updateList, corpid);
                RuleBusinessLogDTO businessLogDTO = new RuleBusinessLogDTO();
                BeanUtil.copyProperties(instockUpdateByBusinessRuleDTO, businessLogDTO);
                businessLogDTO.setFormDataList(formDataList);
                ruleBusinessLogger.writeLog(businessLogDTO, updateList);
            }
        } catch (Exception e) {
            LOG.error("instockService.updateFormDataByBusinessRule根据业务规则更新数据出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
    }

    @Override
    public void dataConsistencyUpdateSeriNo(String corpid, Long dataId, String serialNo) throws XbbException {
        try {
            BoolQueryBuilder filter = boolQuery()
                    .filter(termQuery("corpid.keyword", corpid))
                    .filter(termQuery("del", 0))
                    .filter(termQuery(InstockEnum.getEsAttr4Keyword(InstockEnum.TYPE), InstockTypeEnum.PURCHASE_INSTOCK.getCode()))
                    .filter(termQuery(InstockEnum.getEsAttr4Keyword(InstockEnum.REF_ID),dataId));
            List<String> fieldList = new ArrayList<>();
            fieldList.add(FieldTypeEnum.DATAID.getAlias());
            List<PaasFormDataEntityExt> esEntities = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_INSTOCK, filter, PaasFormDataEntityExt.class, fieldList);
            Set<Long> ids = new HashSet<>();
            for (PaasFormDataEntityExt esEntity : esEntities) {
                ids.add(esEntity.getDataId());
            }
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("corpid", corpid);
            param.put("idIn", ids);
            param.put("del", 0);
            List<InstockEntityExt> instockEntityExts = instockModel.findEntitys(param);
            if (Objects.nonNull(instockEntityExts) && !instockEntityExts.isEmpty()) {
                List<InstockUpdateDTO> instockUpdateDTOList = new ArrayList<>();
                for (InstockEntityExt entityExt : instockEntityExts) {
                    JSONObject data = new JSONObject();
                    data.put(InstockEnum.REF_ID_LINKED_TEXT.getAttr(), serialNo);
                    InstockUpdateDTO instockUpdateDTO = new InstockUpdateDTO();
                    instockUpdateDTO.setId(entityExt.getId());
                    instockUpdateDTO.setData(data);
                    instockUpdateDTOList.add(instockUpdateDTO);
                }

                InstockUpdateBatchDTO instockUpdateBatchDTO = new InstockUpdateBatchDTO();
                instockUpdateBatchDTO.setCorpid(corpid);
                instockUpdateBatchDTO.setOutstockList(instockUpdateDTOList);
                updateBatch(instockUpdateBatchDTO);
            }

        } catch (Exception e) {
            LOG.error("InstockServiceImpl.dataConsistencyUpdateSeriNo 出错， corpid=" + corpid + "  Instock.ref_id=" + dataId + "  SeriNo=" + serialNo, e);
        }
    }

    @Override
    public void formatBatchExplain(List<FieldAttrEntity> fieldAttrEntityList, String enable) {
        String productAttr = InstockEnum.PRODUCT.getAttr();
        BatchSeqExplainHelp.getInstance().formatExplain4BatchAffectProductAttr(fieldAttrEntityList, enable, productAttr);
    }

    /**
     * 供应商名称一致性同步
     * @param corpid 公司ID
     * @param supplierId 供应商id
     * @param supplierName 供应商名称
     * @throws XbbException
     * @since v1.0
     * @version v1.0
     */
    @Override
    public void dataConsistencyUpdateSupplier(String corpid, Long supplierId, String supplierName) throws XbbException {
        try {
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put(ParameterConstant.CORPID, corpid);
            param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
            param.put("type", InstockTypeEnum.PURCHASE_INSTOCK.getCode());
            param.put("supplierid", supplierId);
            List<InstockEntityExt> entityExts = instockModel.getBySupplierId(param);
            //更新数据库的中的data的text_67供应商名称
            List ids = new ArrayList();
            List<UpdateDataEntity> updateDataEntityList = new ArrayList<>();
            if(Objects.nonNull(entityExts)){
                for (InstockEntityExt entityExt : entityExts) {
                    ids.add(entityExt.getId());
                    JSONObject data1 = entityExt.getData();
                    data1.put(ReturnedPurchaseEnum.LINK_SUPPLIER_HIDE.getAttr(),supplierName);
                    updateDataEntityList.add(ExplainUtil.getUpdateData(entityExt.getDataId(),data1, corpid));
                }
                instockModel.updateBatch(updateDataEntityList, corpid);
            }
        }catch (Exception e){
            LOG.error("InstockServiceImpl.dataConsistencyUpdateSupplier 出错，corpid=" + corpid + "  supplierId=" + supplierId + " supplierName=" + supplierName, e);
        }
    }

    @Override
    public void updateBatchLabelAttr(AddLabelDTO addLabelDTO, List<PaasFormDataEntityExt> addBatchList, Boolean addOrDelete) throws XbbException {
        InstockUpdateBatchDTO instockUpdateBatchDTO = new InstockUpdateBatchDTO();
        BeanUtil.copyProperties(addLabelDTO, instockUpdateBatchDTO);
        List<InstockUpdateDTO> instockList = new ArrayList<>();
        addBatchList.forEach(item->{
            InstockUpdateDTO updateDTO = new InstockUpdateDTO();
            updateDTO.setData(item.getData());
            updateDTO.setId(item.getId());
            instockList.add(updateDTO);
        });
        instockUpdateBatchDTO.setOutstockList(instockList);
        updateBatch(instockUpdateBatchDTO);

    }

    @Override
    public void afterSaveForWorkflow(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
        // 逻辑改为仅新建进行入库单保存后逻辑：产品保存，库存更新，上游单据更新
        JSONObject data = saasFormSaveDTO.getNewData();
        String corpid = saasFormSaveDTO.getCorpid();
        JSONArray productJsonArray = data.getJSONArray(InstockEnum.PRODUCT.getAttr());
        PaasFormDataEntity newEntity = saasFormSaveDTO.getNewPaasFormDataEntity();
        Long instockId = newEntity.getId();
        Integer type = data.getInteger(InstockEnum.TYPE.getAttr());
        Long refId = Objects.isNull(data.getLong(InstockEnum.REF_ID.getAttr())) ? 0L : data.getLong(InstockEnum.REF_ID.getAttr());
        Long formId = saasFormSaveDTO.getNewPaasFormDataEntity().getFormId();
        saveProduct(productJsonArray, corpid, instockId,type,refId,formId, true);
        // 序列号入库
//        productSerialService.saveSerialForWorkflow(saasFormSaveDTO, productStr);
    }

    @Override
    public void afterSaveForUpdateWorkflow(SaasFormSaveDTO saasFormSaveDTO) throws XbbException {
        Integer taskType = saasFormSaveDTO.getTaskType();
        boolean isCommitAgain = Objects.equals(taskType, TaskTypeEnum.AGAIN_COMMIT.getType());
        String corpid = saasFormSaveDTO.getCorpid();
        List<InstockProductEntity> outstockProductEntityList = instockProductModel.getProductsByInstockIdIn( saasFormSaveDTO.getCorpid(), saasFormSaveDTO.getNewPaasFormDataEntity().getDataId(), Arrays.asList( DelEnum.NORMAL.getDel(), DelEnum.APPROVE_FAILED.getDel()));
        Set<Long> outStockProductIdList = new HashSet<>();
        // 编辑前的产品数量map
        Map<Long,Double> beforeMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long,InstockProductEntity> beforeEntitMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<InstockProductEntity> beforeEntityList = new ArrayList<>();
        // 编辑后的产品数量Map
        Map<Long,Double> afterMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        outstockProductEntityList.forEach(item->{
            outStockProductIdList.add(item.getId());
            beforeEntitMap.put(item.getId(),item);
        });
        JSONArray updateInstockProductList = new JSONArray();
        JSONArray insertInstockProductList = new JSONArray();
        JSONObject data = saasFormSaveDTO.getNewData();
        List<Long> updateInstockProductIds = new ArrayList<>();
        List<Long> updateProductIds = new ArrayList<>();
        JSONArray productJsonArray = data.getJSONArray(InstockEnum.PRODUCT.getAttr());
        String productStr = JSON.toJSONString(productJsonArray);
        for (int i = 0; i < productJsonArray.size(); i++) {
            JSONObject instockProduct = productJsonArray.getJSONObject(i);
            Long instockProductId = instockProduct.getLong(BusinessConstant.PRODUCT_SUB_ID);
            if (instockProductId != null) {
                updateInstockProductIds.add(instockProductId);
                updateInstockProductList.add(instockProduct);
                beforeEntityList.add(beforeEntitMap.get(instockProductId));
                Long productId = instockProduct.getLong(InstockProductEnum.PRODUCT.getAttr());
                updateProductIds.add(productId);
                if (afterMap.containsKey(productId)){
                    afterMap.put(productId,Arith.add(afterMap.get(productId),instockProduct.getDouble(InstockProductEnum.NUM.getAttr())));
                }else {
                    afterMap.put(productId,instockProduct.getDouble(InstockProductEnum.NUM.getAttr()));
                }
            } else {
                insertInstockProductList.add(instockProduct);
            }
        }
        PaasFormDataEntity newEntity = saasFormSaveDTO.getNewPaasFormDataEntity();
        Long instockId = newEntity.getId();
        Integer type = data.getInteger(InstockEnum.TYPE.getAttr());
        Long refId = Objects.isNull(data.getLong(InstockEnum.REF_ID.getAttr())) ? 0L : data.getLong(InstockEnum.REF_ID.getAttr());
        Long formId = saasFormSaveDTO.getNewPaasFormDataEntity().getFormId();
        if (!insertInstockProductList.isEmpty()) {
            saveProduct(insertInstockProductList, corpid, instockId,type,refId,formId, true);
        }
        updateinsotckProduct(updateInstockProductList, corpid, instockId, type, refId, formId);
        // 采购入库处理智能补货数据
        if (CollectionsUtil.isNotEmpty(updateInstockProductIds) && Objects.equals(InstockTypeEnum.PURCHASE_INSTOCK.getCode(),type)){
            if (CollectionsUtil.isNotEmpty(beforeEntityList)){
                for (InstockProductEntity entity : beforeEntityList) {
                    Double productNum = entity.getProductNum();
                    Long productId = entity.getProductId();
                    if (beforeMap.containsKey(productId)){
                        beforeMap.put(productId,Arith.add(beforeMap.get(productId),productNum));
                    }else {
                        beforeMap.put(productId,productNum);
                    }
                }
            }
            Map<Long,Double> changeNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (Long productId : updateProductIds) {
                // 重新提交的话 是变化前数量为0
                Double beforeNunm = 0D;
                if (!isCommitAgain){
                    beforeNunm = beforeMap.getOrDefault(productId, 0D);
                }
                Double afterNum = afterMap.getOrDefault(productId, 0D);
                changeNumMap.put(productId,Arith.sub(afterNum,beforeNunm));
            }
            List<SmartReplenishmentEntity> smartReplenishmentEntities = smartReplenishmentModel.getByProductList(corpid, updateProductIds);
            if (CollectionsUtil.isNotEmpty(smartReplenishmentEntities)){
                for (SmartReplenishmentEntity smartReplenishmentEntity : smartReplenishmentEntities) {
                    Long productId = smartReplenishmentEntity.getProductId();
                    Double changeNum = changeNumMap.getOrDefault(productId, 0D);
                    Double pendingInstockNum = smartReplenishmentEntity.getPendingInstockNum();
                    // 新建待入库数量 = 原待入库数量 - 变化量
                    smartReplenishmentEntity.setPendingInstockNum(Arith.sub(pendingInstockNum,changeNum));
                }
                try {
                    smartReplenishmentModel.updateBatch(smartReplenishmentEntities,corpid);
                }catch (Exception e){
                    LOG.error("InstockServiceImpl.afterSaveForUpdateWorkflow() 更新智能补货表数据时出错", e);
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
                }

            }
        }
        outStockProductIdList.removeAll(updateInstockProductIds);
        if (CollectionsUtil.isNotEmpty(outStockProductIdList)) {
            instockProductModel.deleteBatchById(outStockProductIdList, corpid, DelEnum.DELETE.getDel());
            Map<Long,Double> delNumMap = new HashMap<>();
            List<Long> delProductIdList = new ArrayList<>();
            for (Long instockProductId : outStockProductIdList) {
                InstockProductEntity entity = beforeEntitMap.get(instockProductId);
                Long productId = entity.getProductId();
                delProductIdList.add(productId);
                Double productNum = entity.getProductNum();
                if (delNumMap.containsKey(productId)){
                    delNumMap.put(productId,Arith.add(delNumMap.get(productId),productNum));
                }else {
                    delNumMap.put(productId,productNum);
                }
            }
            List<SmartReplenishmentEntity> smartReplenishmentEntityList = smartReplenishmentModel.getByProductList(corpid, delProductIdList);
            if (CollectionsUtil.isNotEmpty(smartReplenishmentEntityList)){
                for (SmartReplenishmentEntity smartReplenishmentEntity : smartReplenishmentEntityList) {
                    Long productId = smartReplenishmentEntity.getProductId();
                    Double delNum = delNumMap.getOrDefault(productId, 0D);
                    Double pendingInstockNum = smartReplenishmentEntity.getPendingInstockNum();
                    // 新的待入库数量 = 旧待入库数量 + 删除的待入库数量
                    smartReplenishmentEntity.setPendingInstockNum(Arith.add(pendingInstockNum,delNum));
                }
                try {
                    smartReplenishmentModel.updateBatch(smartReplenishmentEntityList,corpid);
                }catch (Exception e){
                    LOG.error("InstockServiceImpl.afterSaveForUpdateWorkflow() 更新智能补货表数据时出错", e);
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
                }
            }

        }
    }

    /**
     * 更新出库单的出库产品，给工作流审批使用
     * @param productArray
     * @param corpid
     * @param instockId
     * @param type
     * @param refId
     * @param formId
     * @return
     * @throws XbbException
     */
    public List<InstockProductEntity> updateinsotckProduct(JSONArray productArray, String corpid, Long instockId, Integer type, Long refId, Long formId) throws XbbException {
        if (productArray == null || productArray.isEmpty()) {
            return new ArrayList<>();
        }
        // 更新
        List<InstockProductEntity> addInstockProductEntityList = new ArrayList<>();
        Map<Long, PaasFormDataEntityExt> productMap = formDataValidateProductHelp.product2saveMap(corpid,productArray);
        long now = DateTimeUtil.getInt();
        for (int i = 0; i < productArray.size(); i++) {
            JSONObject jsonObject = productArray.getJSONObject(i);
            // 移除序列号相关数据，不存入关联产品数据中
            jsonObject.remove(ProductConstant.SEQ);
            jsonObject.remove(ProductEnum.ENABLE_SERIAL_NUMBER.getSaasAttr());
            jsonObject.remove(ProductEnum.ENABLE_BATCH_SHELF_LIFE.getSaasAttr());

            Long pageProductId = jsonObject.getLong(SelectProductEnum.PRODUCT.getAttr());

            JSONObject productData = productMap.get(pageProductId).getData();
            InstockProductEntity entity = new InstockProductEntity();
            entity.setId(jsonObject.getLong(BusinessConstant.PRODUCT_SUB_ID));
            entity.setCorpid(corpid);
            entity.setProductId(pageProductId);
            entity.setParentId(productData.getLong(ProductEnum.PARENT_ID.getAttr()));
            jsonObject.put(ProductEnum.PARENT_ID.getSaasAttr(), productData.getLong(ProductEnum.PARENT_ID.getAttr()));
            entity.setProductNo(productData.getString(ProductEnum.PRODUCT_NO.getAttr()));
            entity.setProductNum(jsonObject.getDouble(InstockProductEnum.NUM.getAttr()));
            entity.setIntoWarehouseId(instockId);
            entity.setOutstockNum(0D);
            if (Objects.nonNull(jsonObject.getLong(BusinessConstant.REF_PRODUCT_ID))) {
                entity.setRefProductId(jsonObject.getLong(BusinessConstant.REF_PRODUCT_ID));
            }
            saasSaveHelp.formatLinkBusiness4Save(jsonObject, InstockProductEnum.WAREHOUSE.getAttr(), "warehouseName", FieldTypeEnum.LINK_BUSINESS_SINGLE.getType());
            entity.setWarehouseId(jsonObject.getLong(InstockProductEnum.WAREHOUSE.getAttr()));
            entity.setWarehouseName(jsonObject.getString("warehouseName"));
            entity.setProductName(productData.getString(ProductEnum.NAME.getAttr()));
            entity.setProductSpecification(productData.getString(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr()));
            entity.setType(type);
            entity.setPrice(jsonObject.getDouble(SelectProductEnum.PRICE.getAttr()));
            entity.setRefId(refId);
            entity.setFormId(formId);
            entity.setMemo(jsonObject.getString(InstockProductEnum.MEMO.getAttr()));
            entity.setBatch(Objects.isNull(jsonObject.getString(InstockProductEnum.BATCH.getAttr())) ? "" : jsonObject.getString(InstockProductEnum.BATCH.getAttr()));
            Long guaranteePeriod = Objects.isNull(jsonObject.getLong(InstockProductEnum.GUARANTEE_PERIOD.getAttr())) ? 0L : jsonObject.getLong(InstockProductEnum.GUARANTEE_PERIOD.getAttr()) * TimeConstant.SECONDS_PER_DAY;
            entity.setGuaranteePeriod(guaranteePeriod);
            Long produceDate = Objects.isNull(jsonObject.getLong(InstockProductEnum.PRODUCE_DATE.getAttr())) ? 0L : jsonObject.getLong(InstockProductEnum.PRODUCE_DATE.getAttr());
            entity.setProduceDate(produceDate);
            entity.setCost(Objects.isNull(jsonObject.getDouble(InstockProductEnum.COST.getAttr())) ? 0D : jsonObject.getDouble(InstockProductEnum.COST.getAttr()));
            jsonObject.put(InstockProductEnum.TOTAL_COST.getAttr(), Arith.mul(entity.getCost(), entity.getProductNum()));
            entity.setData(jsonObject);
            entity.setDel(0);
            Integer enableMultiUnit = productData.getInteger(ProductEnum.ENABLE_MULTI_UNIT.getAttr());
            if (Objects.equals(enableMultiUnit, 1)) {
                formDataValidateProductHelp.setBusinessUnit(jsonObject, entity);
                entity.setProductUnit(jsonObject.getString(SelectProductEnum.UNIT.getAttr()));
            } else {
                entity.setProductUnit(productData.getString(ProductEnum.UNIT.getAttr()));
                jsonObject.put(InstockProductEnum.UNIT.getAttr(),productData.getString(ProductEnum.UNIT.getAttr()));
            }
            addInstockProductEntityList.add(entity);

        }
        instockProductModel.updateMulti(addInstockProductEntityList, corpid);
        return addInstockProductEntityList;
    }

    @Override
    public void formatBatchOrSeqExplain(List<FieldAttrEntity> fieldAttrEntityList, String enable, String alias) {
        if (CompanyConfigEnum.ENABLE_BATCH_SHELF_MANAGEMENT.getAlias().equals(alias)) {
            formatBatchExplain(fieldAttrEntityList, enable);
        }
    }
}
